1 /*
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
4 *
5 * $Revision: 11866 $
6 * $Id: main.cpp 11866 2019-09-29 16:10:16Z fuscated $
7 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/src/main.cpp $
8 */
9
10 #include <sdk.h>
11
12 #include "app.h"
13 #include "appglobals.h"
14 #include "batchbuild.h"
15 #include "cbart_provider.h"
16 #include "cbauibook.h"
17 #include "cbstyledtextctrl.h"
18 #include "compilersettingsdlg.h"
19 #include "debuggersettingsdlg.h"
20 #include "dlgabout.h"
21 #include "dlgaboutplugin.h"
22 #include "environmentsettingsdlg.h"
23 #include "infopane.h"
24 #include "infowindow.h"
25 #include "main.h"
26 #include "notebookstyles.h"
27 #include "printdlg.h"
28 #include "scriptconsole.h"
29 #include "scriptingsettingsdlg.h"
30 #include "startherepage.h"
31 #include "switcherdlg.h"
32 #include "cbstatusbar.h"
33 #include "loggers.h"
34
35 #include <wx/display.h>
36 #include <wx/dnd.h>
37 #include <wx/fileconf.h>
38 #include <wx/filename.h>
39 #include <wx/gdicmn.h>
40 #include <wx/printdlg.h>
41 #include <wx/sstream.h>
42 #include <wx/tipdlg.h>
43 #include <wx/tokenzr.h>
44 #include <wx/xrc/xmlres.h>
45
46 #include <annoyingdialog.h>
47 #include <cbexception.h>
48 #include <cbplugin.h>
49 #include <cbproject.h>
50 #include <cbworkspace.h>
51 #include <ccmanager.h>
52 #include <configmanager.h>
53 #include <debuggermanager.h>
54 #include <editorcolourset.h>
55 #include <editormanager.h>
56 #include <filefilters.h>
57 #include <globals.h>
58 #include <logmanager.h>
59 #include <personalitymanager.h>
60 #include <pluginmanager.h>
61 #include <projectmanager.h>
62 #include <scriptingmanager.h>
63 #include <sdk_events.h>
64 #include <templatemanager.h>
65 #include <toolsmanager.h>
66 #include <uservarmanager.h>
67
68 #include "debugger_interface_creator.h"
69 #include "debuggermenu.h"
70
71 #include "cbcolourmanager.h"
72 #include "editorconfigurationdlg.h"
73 #include "projectmanagerui.h"
74
75 class cbFileDropTarget : public wxFileDropTarget
76 {
77 public:
cbFileDropTarget(MainFrame * frame)78 cbFileDropTarget(MainFrame *frame):m_frame(frame){}
OnDropFiles(wxCoord x,wxCoord y,const wxArrayString & filenames)79 bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) override
80 {
81 if (!m_frame) return false;
82 return m_frame->OnDropFiles(x,y,filenames);
83 }
84 private:
85 MainFrame* m_frame;
86 };
87
88 const static wxString gDefaultLayout = _T("Code::Blocks default");
89 static wxString gDefaultLayoutData; // this will keep the "hardcoded" default layout
90 static wxString gDefaultMessagePaneLayoutData; // this will keep default layout
91
92 const static wxString gMinimalLayout = _T("Code::Blocks minimal");
93 static wxString gMinimalLayoutData; // this will keep the "hardcoded" default layout
94 static wxString gMinimalMessagePaneLayoutData; // this will keep default layout
95
96 // In <wx/defs.h> wxID_FILE[X] exists only from 1..9,
97 // so create our own here with a *continuous* numbering!
98 // The wxID_FILE[X] enum usually starts at 5050 until 5059,
99 // followed by wxID_OK starting at 5100. (wxWidgets v2.6, v2.8 and v2.9)
100 // so we use the space in between starting from 5060
101 // and hoping it doesn't change too much in <wx/defs.h> ;-)
102 enum
103 {
104 wxID_CBFILE01 = 5060, // Recent files...
105 wxID_CBFILE02, // 5061
106 wxID_CBFILE03, // 5062
107 wxID_CBFILE04, // 5063
108 wxID_CBFILE05, // 5064
109 wxID_CBFILE06, // 5065
110 wxID_CBFILE07, // 5066
111 wxID_CBFILE08, // 5067
112 wxID_CBFILE09, // 5068
113 wxID_CBFILE10, // 5069
114 wxID_CBFILE11, // 5070
115 wxID_CBFILE12, // 5071
116 wxID_CBFILE13, // 5072
117 wxID_CBFILE14, // 5073
118 wxID_CBFILE15, // 5074
119 wxID_CBFILE16, // 5075
120 wxID_CBFILE17, // 5076 // Starting here for recent projects...
121 wxID_CBFILE18, // 5077
122 wxID_CBFILE19, // 5078
123 wxID_CBFILE20, // 5079
124 wxID_CBFILE21, // 5080
125 wxID_CBFILE22, // 5081
126 wxID_CBFILE23, // 5082
127 wxID_CBFILE24, // 5083
128 wxID_CBFILE25, // 5084
129 wxID_CBFILE26, // 5085
130 wxID_CBFILE27, // 5086
131 wxID_CBFILE28, // 5087
132 wxID_CBFILE29, // 5088
133 wxID_CBFILE30, // 5089
134 wxID_CBFILE31, // 5090
135 wxID_CBFILE32 // 5091
136 };
137
138 int idToolNew = XRCID("idToolNew");
139 int idFileNew = XRCID("idFileNew");
140 int idFileNewEmpty = XRCID("idFileNewEmpty");
141 int idFileNewProject = XRCID("idFileNewProject");
142 int idFileNewTarget = XRCID("idFileNewTarget");
143 int idFileNewFile = XRCID("idFileNewFile");
144 int idFileNewCustom = XRCID("idFileNewCustom");
145 int idFileNewUser = XRCID("idFileNewUser");
146 int idFileOpen = XRCID("idFileOpen");
147 int idFileReopen = XRCID("idFileReopen");
148 int idFileOpenRecentFileClearHistory = XRCID("idFileOpenRecentFileClearHistory");
149 int idFileOpenRecentProjectClearHistory = XRCID("idFileOpenRecentProjectClearHistory");
150 int idFileImportProjectDevCpp = XRCID("idFileImportProjectDevCpp");
151 int idFileImportProjectMSVC = XRCID("idFileImportProjectMSVC");
152 int idFileImportProjectMSVCWksp = XRCID("idFileImportProjectMSVCWksp");
153 int idFileImportProjectMSVS = XRCID("idFileImportProjectMSVS");
154 int idFileImportProjectMSVSWksp = XRCID("idFileImportProjectMSVSWksp");
155 int idFileSave = XRCID("idFileSave");
156 int idFileSaveAs = XRCID("idFileSaveAs");
157 int idFileReopenProject = XRCID("idFileReopenProject");
158 int idFileSaveProject = XRCID("idFileSaveProject");
159 int idFileSaveProjectAs = XRCID("idFileSaveProjectAs");
160 int idFileSaveProjectTemplate = XRCID("idFileSaveProjectTemplate");
161 int idFileOpenDefWorkspace = XRCID("idFileOpenDefWorkspace");
162 int idFileSaveWorkspace = XRCID("idFileSaveWorkspace");
163 int idFileSaveWorkspaceAs = XRCID("idFileSaveWorkspaceAs");
164 int idFileSaveAll = XRCID("idFileSaveAll");
165 int idFileCloseWorkspace = XRCID("idFileCloseWorkspace");
166 int idFileClose = XRCID("idFileClose");
167 int idFileCloseAll = XRCID("idFileCloseAll");
168 int idFileCloseProject = XRCID("idFileCloseProject");
169 int idFilePrintSetup = XRCID("idFilePrintSetup");
170 int idFilePrint = XRCID("idFilePrint");
171 int idFileExit = XRCID("idFileExit");
172
173 int idEditUndo = XRCID("idEditUndo");
174 int idEditRedo = XRCID("idEditRedo");
175 int idEditClearHistory = XRCID("idEditClearHistory");
176 int idEditCopy = XRCID("idEditCopy");
177 int idEditCut = XRCID("idEditCut");
178 int idEditPaste = XRCID("idEditPaste");
179 int idEditSwapHeaderSource = XRCID("idEditSwapHeaderSource");
180 int idEditGotoMatchingBrace = XRCID("idEditGotoMatchingBrace");
181 int idEditHighlightMode = XRCID("idEditHighlightMode");
182 int idEditHighlightModeText = XRCID("idEditHighlightModeText");
183 int idEditBookmarks = XRCID("idEditBookmarks");
184 int idEditBookmarksToggle = XRCID("idEditBookmarksToggle");
185 int idEditBookmarksPrevious = XRCID("idEditBookmarksPrevious");
186 int idEditBookmarksNext = XRCID("idEditBookmarksNext");
187 int idEditBookmarksClearAll = XRCID("idEditBookmarksClearAll");
188 int idEditFolding = XRCID("idEditFolding");
189 int idEditFoldAll = XRCID("idEditFoldAll");
190 int idEditUnfoldAll = XRCID("idEditUnfoldAll");
191 int idEditToggleAllFolds = XRCID("idEditToggleAllFolds");
192 int idEditFoldBlock = XRCID("idEditFoldBlock");
193 int idEditUnfoldBlock = XRCID("idEditUnfoldBlock");
194 int idEditToggleFoldBlock = XRCID("idEditToggleFoldBlock");
195 int idEditEOLMode = XRCID("idEditEOLMode");
196 int idEditEOLCRLF = XRCID("idEditEOLCRLF");
197 int idEditEOLCR = XRCID("idEditEOLCR");
198 int idEditEOLLF = XRCID("idEditEOLLF");
199 int idEditEncoding = XRCID("idEditEncoding");
200 int idEditEncodingDefault = XRCID("idEditEncodingDefault");
201 int idEditEncodingUseBom = XRCID("idEditEncodingUseBom");
202 int idEditEncodingAscii = XRCID("idEditEncodingAscii");
203 int idEditEncodingUtf7 = XRCID("idEditEncodingUtf7");
204 int idEditEncodingUtf8 = XRCID("idEditEncodingUtf8");
205 int idEditEncodingUnicode = XRCID("idEditEncodingUnicode");
206 int idEditEncodingUtf16 = XRCID("idEditEncodingUtf16");
207 int idEditEncodingUtf32 = XRCID("idEditEncodingUtf32");
208 int idEditEncodingUnicode16BE = XRCID("idEditEncodingUnicode16BE");
209 int idEditEncodingUnicode16LE = XRCID("idEditEncodingUnicode16LE");
210 int idEditEncodingUnicode32BE = XRCID("idEditEncodingUnicode32BE");
211 int idEditEncodingUnicode32LE = XRCID("idEditEncodingUnicode32LE");
212 int idEditSpecialCommands = XRCID("idEditSpecialCommands");
213 int idEditSpecialCommandsMovement = XRCID("idEditSpecialCommandsMovement");
214 int idEditParaUp = XRCID("idEditParaUp");
215 int idEditParaUpExtend = XRCID("idEditParaUpExtend");
216 int idEditParaDown = XRCID("idEditParaDown");
217 int idEditParaDownExtend = XRCID("idEditParaDownExtend");
218 int idEditWordPartLeft = XRCID("idEditWordPartLeft");
219 int idEditWordPartLeftExtend = XRCID("idEditWordPartLeftExtend");
220 int idEditWordPartRight = XRCID("idEditWordPartRight");
221 int idEditWordPartRightExtend = XRCID("idEditWordPartRightExtend");
222 int idEditSpecialCommandsZoom = XRCID("idEditSpecialCommandsZoom");
223 int idEditZoomIn = XRCID("idEditZoomIn");
224 int idEditZoomOut = XRCID("idEditZoomOut");
225 int idEditZoomReset = XRCID("idEditZoomReset");
226 int idEditSpecialCommandsLine = XRCID("idEditSpecialCommandsLine");
227 int idEditLineCut = XRCID("idEditLineCut");
228 int idEditLineDelete = XRCID("idEditLineDelete");
229 int idEditLineDuplicate = XRCID("idEditLineDuplicate");
230 int idEditLineTranspose = XRCID("idEditLineTranspose");
231 int idEditLineCopy = XRCID("idEditLineCopy");
232 int idEditLinePaste = XRCID("idEditLinePaste");
233 int idEditLineUp = XRCID("idEditLineUp");
234 int idEditLineDown = XRCID("idEditLineDown");
235 int idEditSpecialCommandsCase = XRCID("idEditSpecialCommandsCase");
236 int idEditUpperCase = XRCID("idEditUpperCase");
237 int idEditLowerCase = XRCID("idEditLowerCase");
238 int idEditSpecialCommandsOther = XRCID("idEditSpecialCommandsOther");
239 int idEditInsertNewLine = XRCID("idEditInsertNewLine");
240 int idEditGotoLineEnd = XRCID("idEditGotoLineEnd");
241 int idEditInsertNewLineBelow = XRCID("idEditInsertNewLineBelow");
242 int idEditInsertNewLineAbove = XRCID("idEditInsertNewLineAbove");
243 int idEditSelectAll = XRCID("idEditSelectAll");
244 int idEditSelectNext = XRCID("idEditSelectNext");
245 int idEditSelectNextSkip = XRCID("idEditSelectNextSkip");
246 int idEditCommentSelected = XRCID("idEditCommentSelected");
247 int idEditUncommentSelected = XRCID("idEditUncommentSelected");
248 int idEditToggleCommentSelected = XRCID("idEditToggleCommentSelected");
249 int idEditStreamCommentSelected = XRCID("idEditStreamCommentSelected");
250 int idEditBoxCommentSelected = XRCID("idEditBoxCommentSelected");
251 int idEditShowCallTip = XRCID("idEditShowCallTip");
252 int idEditCompleteCode = wxNewId();
253
254 int idViewLayoutDelete = XRCID("idViewLayoutDelete");
255 int idViewLayoutSave = XRCID("idViewLayoutSave");
256 int idViewToolbars = XRCID("idViewToolbars");
257 int idViewToolFit = XRCID("idViewToolFit");
258 int idViewToolOptimize = XRCID("idViewToolOptimize");
259 int idViewToolMain = XRCID("idViewToolMain");
260 int idViewToolDebugger = XRCID("idViewToolDebugger");
261 int idViewManager = XRCID("idViewManager");
262 int idViewLogManager = XRCID("idViewLogManager");
263 int idViewStartPage = XRCID("idViewStartPage");
264 int idViewStatusbar = XRCID("idViewStatusbar");
265 int idViewScriptConsole = XRCID("idViewScriptConsole");
266 int idViewHideEditorTabs = XRCID("idViewHideEditorTabs");
267 int idViewFocusEditor = XRCID("idViewFocusEditor");
268 int idViewFocusManagement = XRCID("idViewFocusManagement");
269 int idViewFocusLogsAndOthers = XRCID("idViewFocusLogsAndOthers");
270 int idViewSwitchTabs = XRCID("idViewSwitchTabs");
271 int idViewFullScreen = XRCID("idViewFullScreen");
272
273 int idSearchFind = XRCID("idSearchFind");
274 int idSearchFindInFiles = XRCID("idSearchFindInFiles");
275 int idSearchFindNext = XRCID("idSearchFindNext");
276 int idSearchFindPrevious = XRCID("idSearchFindPrevious");
277 int idSearchFindSelectedNext = XRCID("idSearchFindSelectedNext");
278 int idSearchFindSelectedPrevious = XRCID("idSearchFindSelectedPrevious");
279 int idSearchReplace = XRCID("idSearchReplace");
280 int idSearchReplaceInFiles = XRCID("idSearchReplaceInFiles");
281 int idSearchGotoLine = XRCID("idSearchGotoLine");
282 int idSearchGotoNextChanged = XRCID("idSearchGotoNextChanged");
283 int idSearchGotoPreviousChanged = XRCID("idSearchGotoPreviousChanged");
284
285 int idSettingsEnvironment = XRCID("idSettingsEnvironment");
286 int idSettingsGlobalUserVars = XRCID("idSettingsGlobalUserVars");
287 int idSettingsEditor = XRCID("idSettingsEditor");
288 int idSettingsCompiler = XRCID("idSettingsCompiler");
289 int idSettingsDebugger = XRCID("idSettingsDebugger");
290 int idPluginsManagePlugins = XRCID("idPluginsManagePlugins");
291 int idSettingsScripting = XRCID("idSettingsScripting");
292
293 int idHelpTips = XRCID("idHelpTips");
294 int idHelpPlugins = XRCID("idHelpPlugins");
295
296 int idLeftSash = XRCID("idLeftSash");
297 int idBottomSash = XRCID("idBottomSash");
298 int idCloseFullScreen = XRCID("idCloseFullScreen");
299
300 int idGetGlobalAccels = XRCID("idGetGlobalAccels");
301
302 int idFileNext = wxNewId();
303 int idFilePrev = wxNewId();
304 int idShiftTab = wxNewId();
305 int idCtrlAltTab = wxNewId();
306 int idStartHerePageLink = wxNewId();
307 int idHighlightButton = wxNewId();
308
BEGIN_EVENT_TABLE(MainFrame,wxFrame)309 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
310 EVT_ERASE_BACKGROUND(MainFrame::OnEraseBackground)
311 EVT_SIZE(MainFrame::OnSize)
312 EVT_CLOSE(MainFrame::OnApplicationClose)
313
314 EVT_UPDATE_UI(idFileOpen, MainFrame::OnFileMenuUpdateUI)
315 EVT_UPDATE_UI(idFileOpenRecentFileClearHistory, MainFrame::OnFileMenuUpdateUI)
316 EVT_UPDATE_UI(idFileOpenRecentProjectClearHistory, MainFrame::OnFileMenuUpdateUI)
317 EVT_UPDATE_UI(idFileSave, MainFrame::OnFileMenuUpdateUI)
318 EVT_UPDATE_UI(idFileSaveAs, MainFrame::OnFileMenuUpdateUI)
319 EVT_UPDATE_UI(idFileOpenDefWorkspace, MainFrame::OnFileMenuUpdateUI)
320 EVT_UPDATE_UI(idFileSaveWorkspace, MainFrame::OnFileMenuUpdateUI)
321 EVT_UPDATE_UI(idFileSaveWorkspaceAs, MainFrame::OnFileMenuUpdateUI)
322 EVT_UPDATE_UI(idFileCloseWorkspace, MainFrame::OnFileMenuUpdateUI)
323 EVT_UPDATE_UI(idFileClose, MainFrame::OnFileMenuUpdateUI)
324 EVT_UPDATE_UI(idFileCloseAll, MainFrame::OnFileMenuUpdateUI)
325 EVT_UPDATE_UI(idFilePrintSetup, MainFrame::OnFileMenuUpdateUI)
326 EVT_UPDATE_UI(idFilePrint, MainFrame::OnFileMenuUpdateUI)
327
328 EVT_UPDATE_UI(idFileReopenProject, MainFrame::OnFileMenuUpdateUI)
329 EVT_UPDATE_UI(idFileSaveProject, MainFrame::OnFileMenuUpdateUI)
330 EVT_UPDATE_UI(idFileSaveProjectAs, MainFrame::OnFileMenuUpdateUI)
331 EVT_UPDATE_UI(idFileSaveProjectTemplate, MainFrame::OnFileMenuUpdateUI)
332 EVT_UPDATE_UI(idFileSaveAll, MainFrame::OnFileMenuUpdateUI)
333 EVT_UPDATE_UI(idFileCloseProject, MainFrame::OnFileMenuUpdateUI)
334
335 EVT_UPDATE_UI(idEditUndo, MainFrame::OnEditMenuUpdateUI)
336 EVT_UPDATE_UI(idEditRedo, MainFrame::OnEditMenuUpdateUI)
337 EVT_UPDATE_UI(idEditClearHistory, MainFrame::OnEditMenuUpdateUI)
338 EVT_UPDATE_UI(idEditCopy, MainFrame::OnEditMenuUpdateUI)
339 EVT_UPDATE_UI(idEditCut, MainFrame::OnEditMenuUpdateUI)
340 EVT_UPDATE_UI(idEditPaste, MainFrame::OnEditMenuUpdateUI)
341 EVT_UPDATE_UI(idEditSwapHeaderSource, MainFrame::OnEditMenuUpdateUI)
342 EVT_UPDATE_UI(idEditGotoMatchingBrace, MainFrame::OnEditMenuUpdateUI)
343 EVT_UPDATE_UI(idEditFoldAll, MainFrame::OnEditMenuUpdateUI)
344 EVT_UPDATE_UI(idEditUnfoldAll, MainFrame::OnEditMenuUpdateUI)
345 EVT_UPDATE_UI(idEditToggleAllFolds, MainFrame::OnEditMenuUpdateUI)
346 EVT_UPDATE_UI(idEditFoldBlock, MainFrame::OnEditMenuUpdateUI)
347 EVT_UPDATE_UI(idEditUnfoldBlock, MainFrame::OnEditMenuUpdateUI)
348 EVT_UPDATE_UI(idEditToggleFoldBlock, MainFrame::OnEditMenuUpdateUI)
349 EVT_UPDATE_UI(idEditEOLCRLF, MainFrame::OnEditMenuUpdateUI)
350 EVT_UPDATE_UI(idEditEOLCR, MainFrame::OnEditMenuUpdateUI)
351 EVT_UPDATE_UI(idEditEOLLF, MainFrame::OnEditMenuUpdateUI)
352 EVT_UPDATE_UI(idEditEncoding, MainFrame::OnEditMenuUpdateUI)
353 EVT_UPDATE_UI(idEditSelectAll, MainFrame::OnEditMenuUpdateUI)
354 EVT_UPDATE_UI(idEditSelectNext, MainFrame::OnEditMenuUpdateUI)
355 EVT_UPDATE_UI(idEditSelectNextSkip, MainFrame::OnEditMenuUpdateUI)
356 EVT_UPDATE_UI(idEditBookmarksToggle, MainFrame::OnEditMenuUpdateUI)
357 EVT_UPDATE_UI(idEditBookmarksNext, MainFrame::OnEditMenuUpdateUI)
358 EVT_UPDATE_UI(idEditBookmarksPrevious, MainFrame::OnEditMenuUpdateUI)
359 EVT_UPDATE_UI(idEditBookmarksClearAll, MainFrame::OnEditMenuUpdateUI)
360 EVT_UPDATE_UI(idEditCommentSelected, MainFrame::OnEditMenuUpdateUI)
361 EVT_UPDATE_UI(idEditUncommentSelected, MainFrame::OnEditMenuUpdateUI)
362 EVT_UPDATE_UI(idEditToggleCommentSelected, MainFrame::OnEditMenuUpdateUI)
363 EVT_UPDATE_UI(idEditStreamCommentSelected, MainFrame::OnEditMenuUpdateUI)
364 EVT_UPDATE_UI(idEditBoxCommentSelected, MainFrame::OnEditMenuUpdateUI)
365 EVT_UPDATE_UI(idEditShowCallTip, MainFrame::OnEditMenuUpdateUI)
366 EVT_UPDATE_UI(idEditCompleteCode, MainFrame::OnEditMenuUpdateUI)
367
368 EVT_UPDATE_UI(idSearchFind, MainFrame::OnSearchMenuUpdateUI)
369 EVT_UPDATE_UI(idSearchFindInFiles, MainFrame::OnSearchMenuUpdateUI)
370 EVT_UPDATE_UI(idSearchFindNext, MainFrame::OnSearchMenuUpdateUI)
371 EVT_UPDATE_UI(idSearchFindPrevious, MainFrame::OnSearchMenuUpdateUI)
372 EVT_UPDATE_UI(idSearchFindSelectedNext, MainFrame::OnSearchMenuUpdateUI)
373 EVT_UPDATE_UI(idSearchFindSelectedPrevious, MainFrame::OnSearchMenuUpdateUI)
374 EVT_UPDATE_UI(idSearchReplace, MainFrame::OnSearchMenuUpdateUI)
375 EVT_UPDATE_UI(idSearchReplaceInFiles, MainFrame::OnSearchMenuUpdateUI)
376 EVT_UPDATE_UI(idSearchGotoLine, MainFrame::OnSearchMenuUpdateUI)
377 EVT_UPDATE_UI(idSearchGotoNextChanged, MainFrame::OnSearchMenuUpdateUI)
378 EVT_UPDATE_UI(idSearchGotoPreviousChanged, MainFrame::OnSearchMenuUpdateUI)
379
380 EVT_UPDATE_UI(idViewToolMain, MainFrame::OnViewMenuUpdateUI)
381 EVT_UPDATE_UI(idViewLogManager, MainFrame::OnViewMenuUpdateUI)
382 EVT_UPDATE_UI(idViewStartPage, MainFrame::OnViewMenuUpdateUI)
383 EVT_UPDATE_UI(idViewManager, MainFrame::OnViewMenuUpdateUI)
384 EVT_UPDATE_UI(idViewStatusbar, MainFrame::OnViewMenuUpdateUI)
385 EVT_UPDATE_UI(idViewScriptConsole, MainFrame::OnViewMenuUpdateUI)
386 EVT_UPDATE_UI(idViewHideEditorTabs, MainFrame::OnViewMenuUpdateUI)
387 EVT_UPDATE_UI(idViewFocusEditor, MainFrame::OnViewMenuUpdateUI)
388 EVT_UPDATE_UI(idViewFocusManagement, MainFrame::OnViewMenuUpdateUI)
389 EVT_UPDATE_UI(idViewFocusLogsAndOthers, MainFrame::OnViewMenuUpdateUI)
390 EVT_UPDATE_UI(idViewFullScreen, MainFrame::OnViewMenuUpdateUI)
391
392 EVT_MENU(idFileNewEmpty, MainFrame::OnFileNewWhat)
393 EVT_MENU(idFileNewProject, MainFrame::OnFileNewWhat)
394 EVT_MENU(idFileNewTarget, MainFrame::OnFileNewWhat)
395 EVT_MENU(idFileNewFile, MainFrame::OnFileNewWhat)
396 EVT_MENU(idFileNewCustom, MainFrame::OnFileNewWhat)
397 EVT_MENU(idFileNewUser, MainFrame::OnFileNewWhat)
398
399 EVT_MENU(idToolNew, MainFrame::OnFileNew)
400 EVT_MENU(idFileOpen, MainFrame::OnFileOpen)
401 EVT_MENU(idFileOpenRecentProjectClearHistory, MainFrame::OnFileOpenRecentProjectClearHistory)
402 EVT_MENU(idFileOpenRecentFileClearHistory, MainFrame::OnFileOpenRecentClearHistory)
403 EVT_MENU_RANGE(wxID_CBFILE01, wxID_CBFILE16, MainFrame::OnFileReopen)
404 EVT_MENU_RANGE(wxID_CBFILE17, wxID_CBFILE32, MainFrame::OnFileReopenProject)
405 EVT_MENU(idFileImportProjectDevCpp, MainFrame::OnFileImportProjectDevCpp)
406 EVT_MENU(idFileImportProjectMSVC, MainFrame::OnFileImportProjectMSVC)
407 EVT_MENU(idFileImportProjectMSVCWksp, MainFrame::OnFileImportProjectMSVCWksp)
408 EVT_MENU(idFileImportProjectMSVS, MainFrame::OnFileImportProjectMSVS)
409 EVT_MENU(idFileImportProjectMSVSWksp, MainFrame::OnFileImportProjectMSVSWksp)
410 EVT_MENU(idFileSave, MainFrame::OnFileSave)
411 EVT_MENU(idFileSaveAs, MainFrame::OnFileSaveAs)
412 EVT_MENU(idFileSaveProject, MainFrame::OnFileSaveProject)
413 EVT_MENU(idFileSaveProjectAs, MainFrame::OnFileSaveProjectAs)
414 EVT_MENU(idFileSaveProjectTemplate, MainFrame::OnFileSaveProjectTemplate)
415 EVT_MENU(idFileOpenDefWorkspace, MainFrame::OnFileOpenDefWorkspace)
416 EVT_MENU(idFileSaveWorkspace, MainFrame::OnFileSaveWorkspace)
417 EVT_MENU(idFileSaveWorkspaceAs, MainFrame::OnFileSaveWorkspaceAs)
418 EVT_MENU(idFileSaveAll, MainFrame::OnFileSaveAll)
419 EVT_MENU(idFileCloseWorkspace, MainFrame::OnFileCloseWorkspace)
420 EVT_MENU(idFileClose, MainFrame::OnFileClose)
421 EVT_MENU(idFileCloseAll, MainFrame::OnFileCloseAll)
422 EVT_MENU(idFileCloseProject, MainFrame::OnFileCloseProject)
423 EVT_MENU(idFilePrint, MainFrame::OnFilePrint)
424 EVT_MENU(idFileExit, MainFrame::OnFileQuit)
425 EVT_MENU(idFileNext, MainFrame::OnFileNext)
426 EVT_MENU(idFilePrev, MainFrame::OnFilePrev)
427
428 EVT_MENU(idEditUndo, MainFrame::OnEditUndo)
429 EVT_MENU(idEditRedo, MainFrame::OnEditRedo)
430 EVT_MENU(idEditClearHistory, MainFrame::OnEditClearHistory)
431 EVT_MENU(idEditCopy, MainFrame::OnEditCopy)
432 EVT_MENU(idEditCut, MainFrame::OnEditCut)
433 EVT_MENU(idEditPaste, MainFrame::OnEditPaste)
434 EVT_MENU(idEditSwapHeaderSource, MainFrame::OnEditSwapHeaderSource)
435 EVT_MENU(idEditGotoMatchingBrace, MainFrame::OnEditGotoMatchingBrace)
436 EVT_MENU(idEditHighlightModeText, MainFrame::OnEditHighlightMode)
437 EVT_MENU(idEditFoldAll, MainFrame::OnEditFoldAll)
438 EVT_MENU(idEditUnfoldAll, MainFrame::OnEditUnfoldAll)
439 EVT_MENU(idEditToggleAllFolds, MainFrame::OnEditToggleAllFolds)
440 EVT_MENU(idEditFoldBlock, MainFrame::OnEditFoldBlock)
441 EVT_MENU(idEditUnfoldBlock, MainFrame::OnEditUnfoldBlock)
442 EVT_MENU(idEditToggleFoldBlock, MainFrame::OnEditToggleFoldBlock)
443 EVT_MENU(idEditEOLCRLF, MainFrame::OnEditEOLMode)
444 EVT_MENU(idEditEOLCR, MainFrame::OnEditEOLMode)
445 EVT_MENU(idEditEOLLF, MainFrame::OnEditEOLMode)
446 EVT_MENU(idEditEncodingDefault, MainFrame::OnEditEncoding)
447 EVT_MENU(idEditEncodingUseBom, MainFrame::OnEditEncoding)
448 EVT_MENU(idEditEncodingAscii, MainFrame::OnEditEncoding)
449 EVT_MENU(idEditEncodingUtf7, MainFrame::OnEditEncoding)
450 EVT_MENU(idEditEncodingUtf8, MainFrame::OnEditEncoding)
451 EVT_MENU(idEditEncodingUnicode, MainFrame::OnEditEncoding)
452 EVT_MENU(idEditEncodingUtf16, MainFrame::OnEditEncoding)
453 EVT_MENU(idEditEncodingUtf32, MainFrame::OnEditEncoding)
454 EVT_MENU(idEditEncodingUnicode16BE, MainFrame::OnEditEncoding)
455 EVT_MENU(idEditEncodingUnicode16LE, MainFrame::OnEditEncoding)
456 EVT_MENU(idEditEncodingUnicode32BE, MainFrame::OnEditEncoding)
457 EVT_MENU(idEditEncodingUnicode32LE, MainFrame::OnEditEncoding)
458 EVT_MENU(idEditParaUp, MainFrame::OnEditParaUp)
459 EVT_MENU(idEditParaUpExtend, MainFrame::OnEditParaUpExtend)
460 EVT_MENU(idEditParaDown, MainFrame::OnEditParaDown)
461 EVT_MENU(idEditParaDownExtend, MainFrame::OnEditParaDownExtend)
462 EVT_MENU(idEditWordPartLeft, MainFrame::OnEditWordPartLeft)
463 EVT_MENU(idEditWordPartLeftExtend, MainFrame::OnEditWordPartLeftExtend)
464 EVT_MENU(idEditWordPartRight, MainFrame::OnEditWordPartRight)
465 EVT_MENU(idEditWordPartRightExtend, MainFrame::OnEditWordPartRightExtend)
466 EVT_MENU(idEditZoomIn, MainFrame::OnEditZoomIn)
467 EVT_MENU(idEditZoomOut, MainFrame::OnEditZoomOut)
468 EVT_MENU(idEditZoomReset, MainFrame::OnEditZoomReset)
469 EVT_MENU(idEditLineCut, MainFrame::OnEditLineCut)
470 EVT_MENU(idEditLineDelete, MainFrame::OnEditLineDelete)
471 EVT_MENU(idEditLineDuplicate, MainFrame::OnEditLineDuplicate)
472 EVT_MENU(idEditLineTranspose, MainFrame::OnEditLineTranspose)
473 EVT_MENU(idEditLineCopy, MainFrame::OnEditLineCopy)
474 EVT_MENU(idEditLinePaste, MainFrame::OnEditLinePaste)
475 EVT_MENU(idEditLineUp, MainFrame::OnEditLineMove)
476 EVT_MENU(idEditLineDown, MainFrame::OnEditLineMove)
477 EVT_MENU(idEditUpperCase, MainFrame::OnEditUpperCase)
478 EVT_MENU(idEditLowerCase, MainFrame::OnEditLowerCase)
479 EVT_MENU(idEditInsertNewLine, MainFrame::OnEditInsertNewLine)
480 EVT_MENU(idEditGotoLineEnd, MainFrame::OnEditGotoLineEnd)
481 EVT_MENU(idEditInsertNewLineBelow, MainFrame::OnEditInsertNewLineBelow)
482 EVT_MENU(idEditInsertNewLineAbove, MainFrame::OnEditInsertNewLineAbove)
483 EVT_MENU(idEditSelectAll, MainFrame::OnEditSelectAll)
484 EVT_MENU(idEditSelectNext, MainFrame::OnEditSelectNext)
485 EVT_MENU(idEditSelectNextSkip, MainFrame::OnEditSelectNextSkip)
486 EVT_MENU(idEditBookmarksToggle, MainFrame::OnEditBookmarksToggle)
487 EVT_MENU(idEditBookmarksNext, MainFrame::OnEditBookmarksNext)
488 EVT_MENU(idEditBookmarksPrevious, MainFrame::OnEditBookmarksPrevious)
489 EVT_MENU(idEditBookmarksClearAll, MainFrame::OnEditBookmarksClearAll)
490 EVT_MENU(idEditCommentSelected, MainFrame::OnEditCommentSelected)
491 EVT_MENU(idEditUncommentSelected, MainFrame::OnEditUncommentSelected)
492 EVT_MENU(idEditToggleCommentSelected, MainFrame::OnEditToggleCommentSelected)
493 EVT_MENU(idEditStreamCommentSelected, MainFrame::OnEditStreamCommentSelected)
494 EVT_MENU(idEditBoxCommentSelected, MainFrame::OnEditBoxCommentSelected)
495 EVT_MENU(idEditShowCallTip, MainFrame::OnEditShowCallTip)
496 EVT_MENU(idEditCompleteCode, MainFrame::OnEditCompleteCode)
497
498 EVT_MENU(idSearchFind, MainFrame::OnSearchFind)
499 EVT_MENU(idSearchFindInFiles, MainFrame::OnSearchFind)
500 EVT_MENU(idSearchFindNext, MainFrame::OnSearchFindNext)
501 EVT_MENU(idSearchFindPrevious, MainFrame::OnSearchFindNext)
502 EVT_MENU(idSearchFindSelectedNext, MainFrame::OnSearchFindNextSelected)
503 EVT_MENU(idSearchFindSelectedPrevious, MainFrame::OnSearchFindNextSelected)
504 EVT_MENU(idSearchReplace, MainFrame::OnSearchReplace)
505 EVT_MENU(idSearchReplaceInFiles, MainFrame::OnSearchReplace)
506 EVT_MENU(idSearchGotoLine, MainFrame::OnSearchGotoLine)
507 EVT_MENU(idSearchGotoNextChanged, MainFrame::OnSearchGotoNextChanged)
508 EVT_MENU(idSearchGotoPreviousChanged, MainFrame::OnSearchGotoPrevChanged)
509
510 EVT_MENU(idViewLayoutSave, MainFrame::OnViewLayoutSave)
511 EVT_MENU(idViewLayoutDelete, MainFrame::OnViewLayoutDelete)
512 EVT_MENU(idViewToolFit, MainFrame::OnViewToolbarsFit)
513 EVT_MENU(idViewToolOptimize, MainFrame::OnViewToolbarsOptimize)
514 EVT_MENU(idViewToolMain, MainFrame::OnToggleBar)
515 EVT_MENU(idViewToolDebugger, MainFrame::OnToggleBar)
516 EVT_MENU(idViewLogManager, MainFrame::OnToggleBar)
517 EVT_MENU(idViewManager, MainFrame::OnToggleBar)
518 EVT_MENU(idViewStatusbar, MainFrame::OnToggleStatusBar)
519 EVT_MENU(idViewScriptConsole, MainFrame::OnViewScriptConsole)
520 EVT_MENU(idViewHideEditorTabs, MainFrame::OnViewHideEditorTabs)
521 EVT_MENU(idViewFocusEditor, MainFrame::OnFocusEditor)
522 EVT_MENU(idViewFocusManagement, MainFrame::OnFocusManagement)
523 EVT_MENU(idViewFocusLogsAndOthers, MainFrame::OnFocusLogsAndOthers)
524 EVT_MENU(idViewSwitchTabs, MainFrame::OnSwitchTabs)
525 EVT_MENU(idViewFullScreen, MainFrame::OnToggleFullScreen)
526 EVT_MENU(idViewStartPage, MainFrame::OnToggleStartPage)
527
528 EVT_MENU(idSettingsEnvironment, MainFrame::OnSettingsEnvironment)
529 EVT_MENU(idSettingsGlobalUserVars, MainFrame::OnGlobalUserVars)
530 EVT_MENU(idSettingsEditor, MainFrame::OnSettingsEditor)
531 EVT_MENU(idSettingsCompiler, MainFrame::OnSettingsCompiler)
532 EVT_MENU(idSettingsDebugger, MainFrame::OnSettingsDebugger)
533 EVT_MENU(idPluginsManagePlugins, MainFrame::OnSettingsPlugins)
534 EVT_MENU(idSettingsScripting, MainFrame::OnSettingsScripting)
535
536 EVT_MENU(wxID_ABOUT, MainFrame::OnHelpAbout)
537 EVT_MENU(idHelpTips, MainFrame::OnHelpTips)
538
539 EVT_MENU(idStartHerePageLink, MainFrame::OnStartHereLink)
540
541 EVT_CBAUIBOOK_LEFT_DCLICK(ID_NBEditorManager, MainFrame::OnNotebookDoubleClick)
542 EVT_NOTEBOOK_PAGE_CHANGED(ID_NBEditorManager, MainFrame::OnPageChanged)
543
544 // Highlightbutton
545 EVT_BUTTON(idHighlightButton, MainFrame::OnHighlightMenu)
546 /// CloseFullScreen event handling
547 EVT_BUTTON(idCloseFullScreen, MainFrame::OnToggleFullScreen)
548
549 /// Shift-Tab bug workaround
550 EVT_MENU(idShiftTab, MainFrame::OnShiftTab)
551 EVT_MENU(idCtrlAltTab, MainFrame::OnCtrlAltTab)
552
553 // Let plugins get copy of global accelerators
554 EVT_MENU(idGetGlobalAccels, MainFrame::OnGetGlobalAccels)
555
556 /// Used for mouse right click in the free area of MainFrame
557 EVT_RIGHT_UP(MainFrame::OnMouseRightUp)
558
559 END_EVENT_TABLE()
560
561 MainFrame::MainFrame(wxWindow* parent)
562 : wxFrame(parent, -1, _T("MainWin"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE),
563 m_LayoutManager(this),
564 m_pAccel(nullptr),
565 m_filesHistory(_("&File"), wxT("/recent_files"), idFileOpenRecentFileClearHistory, wxID_CBFILE01),
566 m_projectsHistory(_("&File"), wxT("/recent_projects"), idFileOpenRecentProjectClearHistory, wxID_CBFILE17),
567 m_pCloseFullScreenBtn(nullptr),
568 m_pEdMan(nullptr),
569 m_pPrjMan(nullptr),
570 m_pPrjManUI(nullptr),
571 m_pLogMan(nullptr),
572 m_pInfoPane(nullptr),
573 m_pToolbar(nullptr),
574 m_ToolsMenu(nullptr),
575 m_HelpPluginsMenu(nullptr),
576 m_ScanningForPlugins(false),
577 m_StartupDone(false), // one-time flag
578 m_InitiatedShutdown(false),
579 m_AutoHideLockCounter(0),
580 m_LastCtrlAltTabWindow(0),
581 m_LastLayoutIsTemp(false),
582 m_pScriptConsole(nullptr),
583 m_pBatchBuildDialog(nullptr),
584 // Highlightbutton
585 m_pHighlightButton(nullptr)
586 {
587 Manager::Get(this); // provide manager with handle to MainFrame (this)
588
589 // register event sinks
590 RegisterEvents();
591
592 // New: Allow drag and drop of files into the editor
593 SetDropTarget(new cbFileDropTarget(this));
594
595 // Accelerator table
596 m_AccelCount = 8;
597 m_pAccelEntries.reset(new wxAcceleratorEntry[m_AccelCount]);
598 m_pAccelEntries[0].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int) 'W', idFileCloseAll);
599 m_pAccelEntries[1].Set(wxACCEL_CTRL | wxACCEL_SHIFT, WXK_F4, idFileCloseAll);
600 m_pAccelEntries[2].Set(wxACCEL_CTRL, (int) 'W', idFileClose);
601 m_pAccelEntries[3].Set(wxACCEL_CTRL, WXK_F4, idFileClose);
602 m_pAccelEntries[4].Set(wxACCEL_CTRL, WXK_F6, idFileNext);
603 m_pAccelEntries[5].Set(wxACCEL_CTRL | wxACCEL_SHIFT, WXK_F6, idFilePrev);
604 m_pAccelEntries[6].Set(wxACCEL_SHIFT, WXK_TAB, idShiftTab);
605 m_pAccelEntries[7].Set(wxACCEL_CTRL | wxACCEL_ALT, WXK_TAB, idCtrlAltTab);
606 m_pAccel.reset(new wxAcceleratorTable(m_AccelCount, m_pAccelEntries.get()));
607
608 SetAcceleratorTable(*m_pAccel);
609
610 // add file filters for supported projects/workspaces
611 FileFilters::AddDefaultFileFilters();
612
613 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
614 CreateIDE();
615
616 #ifdef __WXMSW__
617 SetIcon(wxICON(A_MAIN_ICON));
618 #else
619 SetIcon(wxIcon(app_xpm));
620 #endif // __WXMSW__
621
622 // even it is possible that the statusbar is not visible at the moment, create the statusbar so the plugins can create their own fields on the it:
623 DoCreateStatusBar();
624 SetStatusText(_("Welcome to ")+ appglobals::AppName + _T("!"));
625
626 wxStatusBar *sb = GetStatusBar();
627 if (sb)
628 sb->Show(cfg->ReadBool(_T("/main_frame/statusbar"), true));
629
630 SetTitle(appglobals::AppName + _T(" v") + appglobals::AppVersion);
631
632 LoadWindowSize();
633 ScanForPlugins();
634 CreateToolbars();
635
636 Manager::Get()->GetCCManager();
637
638 // save default view
639 wxString deflayout = cfg->Read(_T("/main_frame/layout/default"));
640 if (deflayout.IsEmpty())
641 cfg->Write(_T("/main_frame/layout/default"), gDefaultLayout);
642 gDefaultLayoutData = m_LayoutManager.SavePerspective(); // keep the "hardcoded" layout handy
643 gDefaultMessagePaneLayoutData = m_pInfoPane->SaveTabOrder();
644 SaveViewLayout(gDefaultLayout, gDefaultLayoutData, gDefaultMessagePaneLayoutData);
645
646 // generate default minimal layout
647 wxAuiPaneInfoArray& panes = m_LayoutManager.GetAllPanes();
648 for (size_t i = 0; i < panes.GetCount(); ++i)
649 {
650 wxAuiPaneInfo& info = panes[i];
651 if (!(info.name == _T("MainPane")))
652 info.Hide();
653 }
654 gMinimalLayoutData = m_LayoutManager.SavePerspective(); // keep the "hardcoded" layout handy
655 gMinimalMessagePaneLayoutData = m_pInfoPane->SaveTabOrder();
656 SaveViewLayout(gMinimalLayout, gMinimalLayoutData, gMinimalMessagePaneLayoutData);
657
658 LoadWindowState();
659
660 ShowHideStartPage();
661
662 RegisterScriptFunctions();
663 RunStartupScripts();
664
665 Manager::Get()->GetLogManager()->DebugLog(_T("Initializing plugins..."));
666 }
667
~MainFrame()668 MainFrame::~MainFrame()
669 {
670 SetAcceleratorTable(wxNullAcceleratorTable);
671
672 DeInitPrinting();
673
674 delete m_debuggerMenuHandler;
675 delete m_debuggerToolbarHandler;
676 }
677
RegisterEvents()678 void MainFrame::RegisterEvents()
679 {
680 Manager* m = Manager::Get();
681
682 m->RegisterEventSink(cbEVT_EDITOR_UPDATE_UI, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorUpdateUI));
683
684 m->RegisterEventSink(cbEVT_PROJECT_ACTIVATE, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnProjectActivated));
685 m->RegisterEventSink(cbEVT_PROJECT_OPEN, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnProjectOpened));
686 m->RegisterEventSink(cbEVT_PROJECT_CLOSE, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnProjectClosed));
687 m->RegisterEventSink(cbEVT_EDITOR_CLOSE, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorClosed));
688 m->RegisterEventSink(cbEVT_EDITOR_OPEN, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorOpened));
689 m->RegisterEventSink(cbEVT_EDITOR_ACTIVATED, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorActivated));
690 m->RegisterEventSink(cbEVT_EDITOR_SAVE, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorSaved));
691 m->RegisterEventSink(cbEVT_EDITOR_MODIFIED, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnEditorModified));
692
693 m->RegisterEventSink(cbEVT_ADD_DOCK_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestDockWindow));
694 m->RegisterEventSink(cbEVT_REMOVE_DOCK_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestUndockWindow));
695 m->RegisterEventSink(cbEVT_SHOW_DOCK_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestShowDockWindow));
696 m->RegisterEventSink(cbEVT_HIDE_DOCK_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnRequestHideDockWindow));
697 m->RegisterEventSink(cbEVT_DOCK_WINDOW_VISIBILITY, new cbEventFunctor<MainFrame, CodeBlocksDockEvent>(this, &MainFrame::OnDockWindowVisibility));
698
699 m->RegisterEventSink(cbEVT_PLUGIN_ATTACHED, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginLoaded));
700 m->RegisterEventSink(cbEVT_PLUGIN_RELEASED, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginUnloaded));
701 m->RegisterEventSink(cbEVT_PLUGIN_INSTALLED, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginInstalled));
702 m->RegisterEventSink(cbEVT_PLUGIN_UNINSTALLED, new cbEventFunctor<MainFrame, CodeBlocksEvent>(this, &MainFrame::OnPluginUninstalled));
703
704 m->RegisterEventSink(cbEVT_UPDATE_VIEW_LAYOUT, new cbEventFunctor<MainFrame, CodeBlocksLayoutEvent>(this, &MainFrame::OnLayoutUpdate));
705 m->RegisterEventSink(cbEVT_QUERY_VIEW_LAYOUT, new cbEventFunctor<MainFrame, CodeBlocksLayoutEvent>(this, &MainFrame::OnLayoutQuery));
706 m->RegisterEventSink(cbEVT_SWITCH_VIEW_LAYOUT, new cbEventFunctor<MainFrame, CodeBlocksLayoutEvent>(this, &MainFrame::OnLayoutSwitch));
707
708 m->RegisterEventSink(cbEVT_ADD_LOG_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnAddLogWindow));
709 m->RegisterEventSink(cbEVT_REMOVE_LOG_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnRemoveLogWindow));
710 m->RegisterEventSink(cbEVT_HIDE_LOG_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnHideLogWindow));
711 m->RegisterEventSink(cbEVT_SWITCH_TO_LOG_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnSwitchToLogWindow));
712 m->RegisterEventSink(cbEVT_GET_ACTIVE_LOG_WINDOW, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnGetActiveLogWindow));
713 m->RegisterEventSink(cbEVT_SHOW_LOG_MANAGER, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnShowLogManager));
714 m->RegisterEventSink(cbEVT_HIDE_LOG_MANAGER, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnHideLogManager));
715 m->RegisterEventSink(cbEVT_LOCK_LOG_MANAGER, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnLockLogManager));
716 m->RegisterEventSink(cbEVT_UNLOCK_LOG_MANAGER, new cbEventFunctor<MainFrame, CodeBlocksLogEvent>(this, &MainFrame::OnUnlockLogManager));
717 }
718
ShowTips(bool forceShow)719 void MainFrame::ShowTips(bool forceShow)
720 {
721 bool showAtStartup = Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/show_tips"), false);
722 if (forceShow || showAtStartup)
723 {
724 wxString tipsFile = ConfigManager::GetDataFolder() + _T("/tips.txt");
725 long tipsIndex = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/next_tip"), 0);
726 wxTipProvider* tipProvider = wxCreateFileTipProvider(tipsFile, tipsIndex);
727 showAtStartup = wxShowTip(this, tipProvider, showAtStartup);
728 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/show_tips"), showAtStartup);
729 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/next_tip"), (int)tipProvider->GetCurrentTip());
730 delete tipProvider;
731 }
732 }
733
CreateIDE()734 void MainFrame::CreateIDE()
735 {
736 int leftW = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left_block_width"), 200);
737 wxSize clientsize = GetClientSize();
738
739 // Create CloseFullScreen Button, and hide it initially
740 m_pCloseFullScreenBtn = new wxButton(this, idCloseFullScreen, _( "Close full screen" ), wxDefaultPosition );
741 m_pCloseFullScreenBtn->Show( false );
742
743 // management panel
744 m_pPrjMan = Manager::Get()->GetProjectManager();
745 if (!Manager::IsBatchBuild())
746 {
747 m_pPrjManUI = new ProjectManagerUI;
748 m_LayoutManager.AddPane( m_pPrjManUI->GetNotebook(),
749 wxAuiPaneInfo().Name(wxT("ManagementPane")).Caption(_("Management")).
750 BestSize(wxSize(leftW, clientsize.GetHeight())).
751 MinSize(wxSize(100,100)).Left().Layer(1) );
752 }
753 else
754 m_pPrjManUI = new BatchProjectManagerUI;
755 m_pPrjMan->SetUI(m_pPrjManUI);
756
757 const double actualScaleFactor = cbGetActualContentScaleFactor(*this);
758 const int targetHeight = floor(16 * actualScaleFactor);
759 const int uiSize16 = cbFindMinSize16to64(targetHeight);
760
761 // All message posted before this call are either lost or sent to stdout/stderr.
762 // On windows stdout and stderr aren't accessible.
763 SetupGUILogging(uiSize16);
764
765 {
766 wxString msg = wxString::Format(wxT("Loaded config file '%s'"),
767 CfgMgrBldr::Get()->GetConfigFile().wx_str());
768 Manager::Get()->GetLogManager()->Log(msg);
769 }
770
771 SetupDebuggerUI();
772
773 {
774 // Setup the art provider with the images stored in manager_resources.zip
775 const wxString prefix = ConfigManager::GetDataFolder()
776 + wxT("/manager_resources.zip#zip:/images");
777 cbArtProvider *provider = new cbArtProvider(prefix);
778
779 provider->AddMapping(wxT("sdk/select_target"), wxT("select_target.png"));
780 provider->AddMapping(wxT("sdk/missing_icon"), wxT("missing_icon.png"));
781
782 wxArtProvider::Push(provider);
783 }
784
785 {
786 // Setup the art provider for the main menu. Use scaling factor detection to determine the
787 // size of the images. Also do this here when we have a main window (probably this doesn't
788 // help us much, because the window hasn't been shown yet).
789
790 Manager::Get()->SetImageSize(uiSize16, Manager::UIComponent::Menus);
791 Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
792 Manager::UIComponent::Menus);
793
794 Manager::Get()->SetImageSize(uiSize16, Manager::UIComponent::Main);
795 Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
796 Manager::UIComponent::Main);
797
798 const wxString prefix = ConfigManager::GetDataFolder() + wxT("/resources.zip#zip:/images");
799 cbArtProvider *provider = new cbArtProvider(prefix);
800
801 provider->AddMapping(wxT("core/file_open"), wxT("fileopen.png"));
802 provider->AddMapping(wxT("core/file_new"), wxT("filenew.png"));
803 provider->AddMapping(wxT("core/history_clear"), wxT("history_clear.png"));
804 provider->AddMapping(wxT("core/file_save"), wxT("filesave.png"));
805 provider->AddMapping(wxT("core/file_save_as"), wxT("filesaveas.png"));
806 provider->AddMapping(wxT("core/file_save_all"), wxT("filesaveall.png"));
807 provider->AddMapping(wxT("core/file_close"), wxT("fileclose.png"));
808 provider->AddMapping(wxT("core/file_print"), wxT("fileprint.png"));
809 provider->AddMapping(wxT("core/exit"), wxT("exit.png"));
810 provider->AddMapping(wxT("core/undo"), wxT("undo.png"));
811 provider->AddMapping(wxT("core/redo"), wxT("redo.png"));
812 provider->AddMapping(wxT("core/edit_cut"), wxT("editcut.png"));
813 provider->AddMapping(wxT("core/edit_copy"), wxT("editcopy.png"));
814 provider->AddMapping(wxT("core/edit_paste"), wxT("editpaste.png"));
815 provider->AddMapping(wxT("core/bookmark_add"), wxT("bookmark_add.png"));
816 provider->AddMapping(wxT("core/find"), wxT("filefind.png"));
817 provider->AddMapping(wxT("core/find_in_files"), wxT("findf.png"));
818 provider->AddMapping(wxT("core/find_next"), wxT("filefindnext.png"));
819 provider->AddMapping(wxT("core/find_prev"), wxT("filefindprev.png"));
820 provider->AddMapping(wxT("core/search_replace"), wxT("searchreplace.png"));
821 provider->AddMapping(wxT("core/search_replace_in_files"), wxT("searchreplacef.png"));
822 provider->AddMapping(wxT("core/goto"), wxT("goto.png"));
823 provider->AddMapping(wxT("core/manage_plugins"), wxT("plug.png"));
824 provider->AddMapping(wxT("core/help_info"), wxT("info.png"));
825 provider->AddMapping(wxT("core/help_idea"), wxT("idea.png"));
826
827 provider->AddMapping(wxT("core/dbg/run"), wxT("dbgrun.png"));
828 provider->AddMapping(wxT("core/dbg/pause"), wxT("dbgpause.png"));
829 provider->AddMapping(wxT("core/dbg/stop"), wxT("dbgstop.png"));
830 provider->AddMapping(wxT("core/dbg/run_to"), wxT("dbgrunto.png"));
831 provider->AddMapping(wxT("core/dbg/next"), wxT("dbgnext.png"));
832 provider->AddMapping(wxT("core/dbg/step"), wxT("dbgstep.png"));
833 provider->AddMapping(wxT("core/dbg/step_out"), wxT("dbgstepout.png"));
834 provider->AddMapping(wxT("core/dbg/next_inst"), wxT("dbgnexti.png"));
835 provider->AddMapping(wxT("core/dbg/step_inst"), wxT("dbgstepi.png"));
836 provider->AddMapping(wxT("core/dbg/window"), wxT("dbgwindow.png"));
837 provider->AddMapping(wxT("core/dbg/info"), wxT("dbginfo.png"));
838
839 provider->AddMappingF(wxT("core/folder_open"), wxT("tree/%dx%d/folder_open.png"));
840 provider->AddMappingF(wxT("core/gear"), wxT("infopane/%dx%d/misc.png"));
841
842 wxArtProvider::Push(provider);
843 }
844
845 {
846 // Setup toolbar sizes
847 const int configSize = cbHelpers::ReadToolbarSizeFromConfig();
848 const int scaledSize = cbFindMinSize16to64(configSize * actualScaleFactor);
849 Manager::Get()->SetImageSize(scaledSize, Manager::UIComponent::Toolbars);
850 Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
851 Manager::UIComponent::Toolbars);
852 }
853
854 CreateMenubar();
855
856 m_pEdMan = Manager::Get()->GetEditorManager();
857 m_pLogMan = Manager::Get()->GetLogManager();
858
859 // editor manager
860 m_LayoutManager.AddPane(m_pEdMan->GetNotebook(), wxAuiPaneInfo().Name(wxT("MainPane")).
861 CentrePane());
862
863 // script console
864 m_pScriptConsole = new ScriptConsole(this, -1);
865 m_LayoutManager.AddPane(m_pScriptConsole, wxAuiPaneInfo().Name(wxT("ScriptConsole")).
866 Caption(_("Scripting console")).Float().MinSize(100,100).FloatingPosition(300, 200).Hide());
867
868 DoUpdateLayout();
869 DoUpdateLayoutColours();
870 DoUpdateEditorStyle();
871
872 m_pEdMan->GetNotebook()->SetDropTarget(new cbFileDropTarget(this));
873 if (m_pPrjManUI->GetNotebook())
874 m_pPrjManUI->GetNotebook()->SetDropTarget(new cbFileDropTarget(this));
875
876 Manager::Get()->GetColourManager()->Load();
877 }
878
879
SetupGUILogging(int uiSize16)880 void MainFrame::SetupGUILogging(int uiSize16)
881 {
882 // allow new docked windows to use be 3/4 of the available space, the default (0.3) is sometimes too small, especially for "Logs & others"
883 m_LayoutManager.SetDockSizeConstraint(0.75,0.75);
884
885 int bottomH = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/bottom_block_height"), 150);
886 wxSize clientsize = GetClientSize();
887
888 LogManager* mgr = Manager::Get()->GetLogManager();
889 Manager::Get()->SetImageSize(uiSize16, Manager::UIComponent::InfoPaneNotebooks);
890 Manager::Get()->SetUIScaleFactor(cbGetContentScaleFactor(*this),
891 Manager::UIComponent::InfoPaneNotebooks);
892
893 if (!Manager::IsBatchBuild())
894 {
895 m_pInfoPane = new InfoPane(this);
896 m_LayoutManager.AddPane(m_pInfoPane, wxAuiPaneInfo().
897 Name(wxT("MessagesPane")).Caption(_("Logs & others")).
898 BestSize(wxSize(clientsize.GetWidth(), bottomH)).//MinSize(wxSize(50,50)).
899 Bottom());
900
901 wxWindow* log;
902
903 for (size_t i = LogManager::app_log; i < LogManager::max_logs; ++i)
904 {
905 if ((log = mgr->Slot(i).GetLogger()->CreateControl(m_pInfoPane)))
906 m_pInfoPane->AddLogger(mgr->Slot(i).GetLogger(), log, mgr->Slot(i).title, mgr->Slot(i).icon);
907 }
908
909 m_findReplace.CreateSearchLog();
910 }
911 else
912 {
913 m_pBatchBuildDialog = new BatchLogWindow(this, _("Code::Blocks - Batch build"));
914 wxSizer* s = new wxBoxSizer(wxVERTICAL);
915 m_pInfoPane = new InfoPane(m_pBatchBuildDialog);
916 s->Add(m_pInfoPane, 1, wxEXPAND);
917 m_pBatchBuildDialog->SetSizer(s);
918
919 // setting &g_null_log causes the app to crash on exit for some reason...
920 mgr->SetLog(new NullLogger, LogManager::app_log);
921 mgr->SetLog(new NullLogger, LogManager::debug_log);
922 }
923
924 mgr->NotifyUpdate();
925 m_pInfoPane->SetDropTarget(new cbFileDropTarget(this));
926 }
927
SetupDebuggerUI()928 void MainFrame::SetupDebuggerUI()
929 {
930 m_debuggerMenuHandler = new DebuggerMenuHandler;
931 m_debuggerToolbarHandler = new DebuggerToolbarHandler(m_debuggerMenuHandler);
932 m_debuggerMenuHandler->SetEvtHandlerEnabled(false);
933 m_debuggerToolbarHandler->SetEvtHandlerEnabled(false);
934 wxWindow* window = Manager::Get()->GetAppWindow();
935 if (window)
936 {
937 window->PushEventHandler(m_debuggerMenuHandler);
938 window->PushEventHandler(m_debuggerToolbarHandler);
939 }
940 m_debuggerMenuHandler->SetEvtHandlerEnabled(true);
941 m_debuggerToolbarHandler->SetEvtHandlerEnabled(true);
942
943 if (!Manager::IsBatchBuild())
944 {
945 Manager::Get()->GetDebuggerManager()->SetInterfaceFactory(new DebugInterfaceFactory);
946 m_debuggerMenuHandler->RegisterDefaultWindowItems();
947 }
948 }
949
950 DECLARE_INSTANCE_TYPE(MainFrame);
951
RegisterScriptFunctions()952 void MainFrame::RegisterScriptFunctions()
953 {
954 SqPlus::SQClassDef<MainFrame>("MainFrame").
955 func(&MainFrame::Open, "Open");
956
957 SqPlus::BindVariable(this, "App", SqPlus::VAR_ACCESS_READ_ONLY);
958 }
959
RunStartupScripts()960 void MainFrame::RunStartupScripts()
961 {
962 ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("scripting"));
963 wxArrayString keys = mgr->EnumerateKeys(_T("/startup_scripts"));
964
965 for (size_t i = 0; i < keys.GetCount(); ++i)
966 {
967 ScriptEntry se;
968 wxString ser;
969 if (mgr->Read(_T("/startup_scripts/") + keys[i], &ser))
970 {
971 se.SerializeIn(ser);
972 if (!se.enabled)
973 continue;
974
975 try
976 {
977 wxString startup = se.script;
978 if (wxFileName(se.script).IsRelative())
979 startup = ConfigManager::LocateDataFile(se.script, sdScriptsUser | sdScriptsGlobal);
980 if (!startup.IsEmpty())
981 {
982 if (!se.registered)
983 Manager::Get()->GetScriptingManager()->LoadScript(startup);
984 else if (!se.menu.IsEmpty())
985 Manager::Get()->GetScriptingManager()->RegisterScriptMenu(se.menu, startup, false);
986 else
987 Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script/function '%s' not loaded: invalid configuration"), se.script.wx_str()));
988 }
989 else
990 Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script '%s' not found"), se.script.wx_str()));
991 }
992 catch (SquirrelError& exception)
993 {
994 Manager::Get()->GetScriptingManager()->DisplayErrors(&exception);
995 }
996 }
997 }
998 }
999
PluginsUpdated(cb_unused cbPlugin * plugin,cb_unused int status)1000 void MainFrame::PluginsUpdated(cb_unused cbPlugin* plugin, cb_unused int status)
1001 {
1002 Freeze();
1003
1004 // menu
1005 RecreateMenuBar();
1006
1007 // update view->toolbars because we re-created the menubar
1008 PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1009 for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1010 {
1011 cbPlugin* plug = plugins[i]->plugin;
1012 const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plug);
1013 if (!info)
1014 continue;
1015
1016 if (m_PluginsTools[plug]) // if plugin has a toolbar
1017 {
1018 // toolbar exists; add the menu item
1019 wxMenu* viewToolbars = nullptr;
1020 GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
1021 if (viewToolbars)
1022 {
1023 if (viewToolbars->FindItem(info->title) != wxNOT_FOUND)
1024 continue;
1025 wxMenuItem* item = AddPluginInMenus(viewToolbars, plug,
1026 (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnToggleBar,
1027 -1, true);
1028 if (item)
1029 {
1030 item->Check(IsWindowReallyShown(m_PluginsTools[plug]));
1031 }
1032 }
1033 }
1034 }
1035
1036 Thaw();
1037 }
1038
RecreateMenuBar()1039 void MainFrame::RecreateMenuBar()
1040 {
1041 Freeze();
1042
1043 wxMenuBar* m = GetMenuBar();
1044 SetMenuBar(nullptr); // unhook old menubar
1045 CreateMenubar(); // create new menubar
1046 delete m; // delete old menubar
1047
1048 // update layouts menu
1049 for (LayoutViewsMap::iterator it = m_LayoutViews.begin(); it != m_LayoutViews.end(); ++it)
1050 {
1051 if (it->first.IsEmpty())
1052 continue;
1053 SaveViewLayout(it->first, it->second,
1054 m_LayoutMessagePane[it->first],
1055 it->first == m_LastLayoutName);
1056 }
1057
1058 Thaw();
1059 }
1060
CreateMenubar()1061 void MainFrame::CreateMenubar()
1062 {
1063 CodeBlocksEvent event(cbEVT_MENUBAR_CREATE_BEGIN);
1064 Manager::Get()->ProcessEvent(event);
1065
1066 int tmpidx;
1067 wxMenuBar* mbar=nullptr;
1068 wxMenu *tools=nullptr, *plugs=nullptr, *pluginsM=nullptr;
1069 wxMenuItem *tmpitem=nullptr;
1070
1071 wxXmlResource* xml_res = wxXmlResource::Get();
1072 wxString resPath = ConfigManager::GetDataFolder();
1073 xml_res->Load(resPath + _T("/resources.zip#zip:main_menu.xrc"));
1074 Manager::Get()->GetLogManager()->DebugLog(_T("Loading menubar..."));
1075 mbar = xml_res->LoadMenuBar(_T("main_menu_bar"));
1076 if (!mbar)
1077 mbar = new wxMenuBar(); // Some error happened.
1078 if (mbar)
1079 SetMenuBar(mbar);
1080
1081 // Find Menus that we'll change later
1082
1083 tmpidx = mbar->FindMenu(_("&Edit"));
1084 if (tmpidx!=wxNOT_FOUND)
1085 {
1086 wxMenu *hl = nullptr;
1087 mbar->FindItem(idEditHighlightModeText, &hl);
1088 if (hl)
1089 {
1090 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
1091 if (colour_set)
1092 {
1093 wxArrayString langs = colour_set->GetAllHighlightLanguages();
1094 for (size_t i = 0; i < langs.GetCount(); ++i)
1095 {
1096 if (i > 0 && !(i % 20))
1097 hl->Break(); // break into columns every 20 items
1098 int id = wxNewId();
1099 hl->AppendRadioItem(id, langs[i],
1100 wxString::Format(_("Switch highlighting mode for current document to \"%s\""), langs[i].wx_str()));
1101 Connect(id, -1, wxEVT_COMMAND_MENU_SELECTED,
1102 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
1103 &MainFrame::OnEditHighlightMode);
1104 }
1105 }
1106 }
1107 const wxLanguageInfo* info = wxLocale::GetLanguageInfo(wxLANGUAGE_DEFAULT);
1108 wxMenu* editMenu = mbar->GetMenu(tmpidx);
1109 if ( info
1110 && ( ( info->Language >= wxLANGUAGE_CHINESE
1111 && info->Language <= wxLANGUAGE_CHINESE_TAIWAN )
1112 || info->Language == wxLANGUAGE_JAPANESE
1113 || info->Language == wxLANGUAGE_KOREAN ) )
1114 {
1115 editMenu->Append(idEditCompleteCode, _("Complete code\tShift-Space"));
1116 }
1117 else
1118 editMenu->Append(idEditCompleteCode, _("Complete code\tCtrl-Space"));
1119 }
1120
1121 tmpidx = mbar->FindMenu(_("&Tools"));
1122 if (tmpidx!=wxNOT_FOUND)
1123 tools = mbar->GetMenu(tmpidx);
1124
1125 tmpidx = mbar->FindMenu(_("P&lugins"));
1126 if (tmpidx!=wxNOT_FOUND)
1127 plugs = mbar->GetMenu(tmpidx);
1128
1129 if ((tmpitem = mbar->FindItem(idHelpPlugins,nullptr)))
1130 pluginsM = tmpitem->GetSubMenu();
1131
1132 m_ToolsMenu = tools ? tools : new wxMenu();
1133 m_PluginsMenu = plugs ? plugs : new wxMenu();
1134 m_HelpPluginsMenu = pluginsM ? pluginsM : new wxMenu();
1135
1136 // core modules: create menus
1137 if (!Manager::IsBatchBuild())
1138 static_cast<ProjectManagerUI*>(m_pPrjManUI)->CreateMenu(mbar);
1139 Manager::Get()->GetDebuggerManager()->SetMenuHandler(m_debuggerMenuHandler);
1140
1141 // ask all plugins to rebuild their menus
1142 PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1143 for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1144 {
1145 cbPlugin* plug = plugins[i]->plugin;
1146 if (plug && plug->IsAttached())
1147 {
1148 if (plug->GetType() == ptTool)
1149 DoAddPlugin(plug);
1150 else
1151 {
1152 AddPluginInHelpPluginsMenu(plug);
1153 try
1154 {
1155 plug->BuildMenu(mbar);
1156 }
1157 catch (cbException& e)
1158 {
1159 e.ShowErrorMessage();
1160 }
1161 }
1162 }
1163 }
1164
1165 Manager::Get()->GetToolsManager()->BuildToolsMenu(m_ToolsMenu);
1166
1167 // Ctrl+Tab workaround for non windows platforms:
1168 if ((platform::carbon) || (platform::gtk))
1169 {
1170 // Find the menu item for tab switching:
1171 tmpidx = mbar->FindMenu(_("&View"));
1172 if (tmpidx != wxNOT_FOUND)
1173 {
1174 wxMenu* view = mbar->GetMenu(tmpidx);
1175 wxMenuItem* switch_item = view->FindItem(idViewSwitchTabs);
1176 if (switch_item)
1177 {
1178 // Change the accelerator for this menu item:
1179 wxString accel;
1180 if (platform::carbon)
1181 accel = wxT("Alt+Tab");
1182 else if (platform::gtk)
1183 accel = wxT("Ctrl+,");
1184 switch_item->SetItemLabel(wxString(_("S&witch tabs")) + wxT("\t") + accel);
1185 }
1186 }
1187 }
1188
1189 SetMenuBar(mbar);
1190 InitializeRecentFilesHistory();
1191
1192 CodeBlocksEvent event2(cbEVT_MENUBAR_CREATE_END);
1193 Manager::Get()->ProcessEvent(event2);
1194 }
1195
CreateToolbars()1196 void MainFrame::CreateToolbars()
1197 {
1198 if (m_pToolbar)
1199 {
1200 SetToolBar(nullptr);
1201 m_pToolbar = nullptr;
1202 }
1203
1204 wxXmlResource* xml_res = wxXmlResource::Get();
1205 wxString resPath = ConfigManager::GetDataFolder();
1206 xml_res->Load(resPath + _T("/resources.zip#zip:main_toolbar.xrc"));
1207 Manager::Get()->GetLogManager()->DebugLog(_T("Loading toolbar..."));
1208
1209 m_pToolbar = Manager::Get()->CreateEmptyToolbar();
1210 Manager::Get()->AddonToolBar(m_pToolbar, _T("main_toolbar"));
1211
1212 m_pToolbar->Realize();
1213
1214 // Right click on the main toolbar will popup a context menu
1215 m_pToolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this);
1216
1217 m_pToolbar->SetInitialSize();
1218
1219 // Right click on the debugger toolbar will popup a context menu
1220 m_debuggerToolbarHandler->GetToolbar()->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this );
1221
1222 std::vector<ToolbarInfo> toolbars;
1223
1224 toolbars.push_back(ToolbarInfo(m_pToolbar, wxAuiPaneInfo().Name(wxT("MainToolbar")).Caption(_("Main Toolbar")), 0));
1225 toolbars.push_back(ToolbarInfo(m_debuggerToolbarHandler->GetToolbar(),
1226 wxAuiPaneInfo(). Name(wxT("DebuggerToolbar")).Caption(_("Debugger Toolbar")),
1227 2));
1228
1229 // ask all plugins to rebuild their toolbars
1230 PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1231 for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1232 {
1233 cbPlugin* plug = plugins[i]->plugin;
1234 if (plug && plug->IsAttached())
1235 {
1236 ToolbarInfo info = DoAddPluginToolbar(plug);
1237 if (info.toolbar)
1238 {
1239 toolbars.push_back(info);
1240 // support showing context menu of the plugins' toolbar
1241 info.toolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
1242 wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this );
1243 }
1244 }
1245 }
1246
1247 std::sort(toolbars.begin(), toolbars.end());
1248
1249 int row = 0, position = 0, rowLength = 0;
1250 int maxLength = GetSize().x;
1251
1252 for (std::vector<ToolbarInfo>::iterator it = toolbars.begin(); it != toolbars.end(); ++it)
1253 {
1254 rowLength += it->toolbar->GetSize().x;
1255 if (rowLength >= maxLength)
1256 {
1257 row++;
1258 position = 0;
1259 rowLength = it->toolbar->GetSize().x;
1260 }
1261 wxAuiPaneInfo paneInfo(it->paneInfo);
1262 m_LayoutManager.AddPane(it->toolbar, paneInfo.ToolbarPane().Top().Row(row).Position(position));
1263
1264 position += it->toolbar->GetSize().x;
1265 }
1266 DoUpdateLayout();
1267
1268 Manager::ProcessPendingEvents();
1269 SetToolBar(nullptr);
1270 }
1271
AddToolbarItem(int id,const wxString & title,const wxString & shortHelp,const wxString & longHelp,const wxString & image)1272 void MainFrame::AddToolbarItem(int id, const wxString& title, const wxString& shortHelp, const wxString& longHelp, const wxString& image)
1273 {
1274 m_pToolbar->AddTool(id, title, cbLoadBitmap(image, wxBITMAP_TYPE_PNG));
1275 m_pToolbar->SetToolShortHelp(id, shortHelp);
1276 m_pToolbar->SetToolLongHelp(id, longHelp);
1277 }
1278
ScanForPlugins()1279 void MainFrame::ScanForPlugins()
1280 {
1281 m_ScanningForPlugins = true;
1282 m_PluginIDsMap.clear();
1283
1284 PluginManager* m_PluginManager = Manager::Get()->GetPluginManager();
1285
1286 // user paths first
1287 wxString path = ConfigManager::GetPluginsFolder(false);
1288 Manager::Get()->GetLogManager()->Log(_("Scanning for plugins in ") + path);
1289 int count = m_PluginManager->ScanForPlugins(path);
1290
1291 // global paths
1292 path = ConfigManager::GetPluginsFolder(true);
1293 Manager::Get()->GetLogManager()->Log(_("Scanning for plugins in ") + path);
1294 count += m_PluginManager->ScanForPlugins(path);
1295
1296 // actually load plugins
1297 if (count > 0)
1298 {
1299 Manager::Get()->GetLogManager()->Log(_("Loading:"));
1300 m_PluginManager->LoadAllPlugins();
1301 }
1302
1303 CodeBlocksEvent event(cbEVT_PLUGIN_LOADING_COMPLETE);
1304 Manager::Get()->GetPluginManager()->NotifyPlugins(event);
1305 m_ScanningForPlugins = false;
1306 }
1307
AddPluginInMenus(wxMenu * menu,cbPlugin * plugin,wxObjectEventFunction callback,int pos,bool checkable)1308 wxMenuItem* MainFrame::AddPluginInMenus(wxMenu* menu, cbPlugin* plugin, wxObjectEventFunction callback, int pos, bool checkable)
1309 {
1310 wxMenuItem* item = nullptr;
1311 if (!plugin || !menu)
1312 return item;
1313
1314 const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1315 if (!info)
1316 return nullptr;
1317
1318 PluginIDsMap::iterator it;
1319 for (it = m_PluginIDsMap.begin(); it != m_PluginIDsMap.end(); ++it)
1320 {
1321 if (it->second == info->name)
1322 {
1323 item = menu->FindItem(it->first);
1324 if (item)
1325 return item;
1326 }
1327 }
1328
1329 int id = wxNewId();
1330 wxString title = info->title + (menu == m_HelpPluginsMenu ? _T("...") : wxEmptyString);
1331 m_PluginIDsMap[id] = info->name;
1332 if (pos == -1)
1333 pos = menu->GetMenuItemCount();
1334
1335 while(!item)
1336 {
1337 if (!pos || title.CmpNoCase(menu->FindItemByPosition(pos - 1)->GetItemLabelText()) > 0)
1338 item = menu->Insert(pos, id, title, wxEmptyString, checkable ? wxITEM_CHECK : wxITEM_NORMAL);
1339
1340 --pos;
1341 }
1342
1343 Connect( id, wxEVT_COMMAND_MENU_SELECTED, callback );
1344 return item;
1345 }
1346
AddPluginInPluginsMenu(cbPlugin * plugin)1347 void MainFrame::AddPluginInPluginsMenu(cbPlugin* plugin)
1348 {
1349 // "Plugins" menu is special case because it contains "Manage plugins",
1350 // which must stay at the end of the menu
1351 // So we insert entries, not append...
1352
1353 // this will insert a separator when the first plugin is added in the "Plugins" menu
1354 if (m_PluginsMenu->GetMenuItemCount() == 1)
1355 m_PluginsMenu->Insert(0, wxID_SEPARATOR, _T(""));
1356
1357 AddPluginInMenus(m_PluginsMenu, plugin,
1358 (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnPluginsExecuteMenu,
1359 m_PluginsMenu->GetMenuItemCount() - 2);
1360 }
1361
AddPluginInHelpPluginsMenu(cbPlugin * plugin)1362 void MainFrame::AddPluginInHelpPluginsMenu(cbPlugin* plugin)
1363 {
1364 AddPluginInMenus(m_HelpPluginsMenu, plugin,
1365 (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnHelpPluginMenu);
1366 }
1367
1368
1369 namespace
1370 {
1371 struct ToolbarFitInfo
1372 {
1373 int row;
1374 wxRect rect;
1375 wxWindow *window;
1376
operator <__anon5b41abdd0211::ToolbarFitInfo1377 bool operator<(const ToolbarFitInfo &r) const
1378 {
1379 if (row < r.row)
1380 return true;
1381 else if (row == r.row)
1382 return rect.x < r.rect.x;
1383 else
1384 return false;
1385 }
1386 };
1387
CollectToolbars(std::set<ToolbarFitInfo> & result,wxAuiManager & layoutManager)1388 static void CollectToolbars(std::set<ToolbarFitInfo> &result, wxAuiManager &layoutManager)
1389 {
1390 const wxAuiPaneInfoArray &panes = layoutManager.GetAllPanes();
1391 for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1392 {
1393 const wxAuiPaneInfo &info = panes[ii];
1394 if (info.IsToolbar() && info.IsShown())
1395 {
1396 ToolbarFitInfo f;
1397 f.row = info.dock_row;
1398 f.rect = info.rect;
1399 f.window = info.window;
1400 result.insert(f);
1401 }
1402 }
1403 }
1404
1405 struct ToolbarRowInfo
1406 {
ToolbarRowInfo__anon5b41abdd0211::ToolbarRowInfo1407 ToolbarRowInfo() {}
ToolbarRowInfo__anon5b41abdd0211::ToolbarRowInfo1408 ToolbarRowInfo(int width_, int position_) : width(width_), position(position_) {}
1409
1410 int width, position;
1411 };
1412
1413 // Function which tries to make all toolbars visible.
FitToolbars(wxAuiManager & layoutManager,wxWindow * mainFrame)1414 static void FitToolbars(wxAuiManager &layoutManager, wxWindow *mainFrame)
1415 {
1416 std::set<ToolbarFitInfo> sorted;
1417 CollectToolbars(sorted, layoutManager);
1418 if (sorted.empty())
1419 return;
1420
1421 int maxWidth = mainFrame->GetSize().x;
1422 int gripperSize = layoutManager.GetArtProvider()->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
1423
1424 // move all toolbars to the left as possible and add the non-fitting to a list
1425 std::vector<ToolbarRowInfo> rows;
1426 std::vector<wxWindow*> nonFitingToolbars;
1427 for (std::set<ToolbarFitInfo>::const_iterator it = sorted.begin(); it != sorted.end(); ++it)
1428 {
1429 wxAuiPaneInfo &pane = layoutManager.GetPane(it->window);
1430 int row = pane.dock_row;
1431 while (static_cast<int>(rows.size()) <= row)
1432 rows.push_back(ToolbarRowInfo(0, 0));
1433
1434 int maxX = rows[row].width + it->window->GetBestSize().x + gripperSize;
1435 if (maxX > maxWidth)
1436 nonFitingToolbars.push_back(it->window);
1437 else
1438 {
1439 rows[row].width = maxX;
1440 pane.Position(rows[row].position++);
1441 }
1442 }
1443
1444 // move the non-fitting toolbars at the bottom
1445 int lastRow = rows.empty() ? 0 : (rows.size() - 1);
1446 int position = rows.back().position, maxX = rows.back().width;
1447 for (std::vector<wxWindow*>::iterator it = nonFitingToolbars.begin(); it != nonFitingToolbars.end(); ++it)
1448 {
1449 maxX += (*it)->GetBestSize().x;
1450 maxX += gripperSize;
1451 if (maxX > maxWidth)
1452 {
1453 position = 0;
1454 lastRow++;
1455 maxX = (*it)->GetBestSize().x + gripperSize;
1456 }
1457 layoutManager.GetPane(*it).Position(position++).Row(lastRow);
1458 }
1459 }
1460
1461 // Function which tries to minimize the space used by the toolbars.
1462 // Also it can be used to show toolbars which have gone outside the window.
OptimizeToolbars(wxAuiManager & layoutManager,wxWindow * mainFrame)1463 static void OptimizeToolbars(wxAuiManager &layoutManager, wxWindow *mainFrame)
1464 {
1465 std::set<ToolbarFitInfo> sorted;
1466 CollectToolbars(sorted, layoutManager);
1467 if (sorted.empty())
1468 return;
1469
1470 int maxWidth = mainFrame->GetSize().x;
1471 int lastRow = 0, position = 0, maxX = 0;
1472 int gripperSize = layoutManager.GetArtProvider()->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
1473
1474 for (std::set<ToolbarFitInfo>::const_iterator it = sorted.begin(); it != sorted.end(); ++it)
1475 {
1476 maxX += it->window->GetBestSize().x;
1477 maxX += gripperSize;
1478 if (maxX > maxWidth)
1479 {
1480 position = 0;
1481 lastRow++;
1482 maxX = it->window->GetBestSize().x + gripperSize;
1483 }
1484 layoutManager.GetPane(it->window).Position(position++).Row(lastRow);
1485 }
1486 }
1487
1488 } // anomymous namespace
1489
LoadWindowState()1490 void MainFrame::LoadWindowState()
1491 {
1492 wxArrayString subs = Manager::Get()->GetConfigManager(_T("app"))->EnumerateSubPaths(_T("/main_frame/layout"));
1493 for (size_t i = 0; i < subs.GetCount(); ++i)
1494 {
1495 wxString name = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/name"));
1496 wxString layout = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/data"));
1497 wxString layoutMP = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/dataMessagePane"));
1498 SaveViewLayout(name, layout, layoutMP);
1499 }
1500 wxString deflayout = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/default"));
1501 LoadViewLayout(deflayout);
1502
1503 DoFixToolbarsLayout();
1504
1505 // Fit toolbars on load to prevent gaps if toolbar sizes have changed. The most common reason
1506 // for toolbar change would be change of the size of the icons in the toolbar.
1507 FitToolbars(m_LayoutManager, this);
1508
1509 // load manager and messages selected page
1510 if (m_pPrjManUI->GetNotebook())
1511 m_pPrjManUI->GetNotebook()->SetSelection(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left_block_selection"), 0));
1512 m_pInfoPane->SetSelection(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/bottom_block_selection"), 0));
1513
1514 // Cryogen 23/3/10 wxAuiNotebook can't set it's own tab position once instantiated, for some reason. This code fails in InfoPane::InfoPane().
1515 // Moved here as this seems like a resonable place to do UI setup. Feel free to move it elsewhere.
1516 if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/infopane_tabs_bottom"), false))
1517 m_pInfoPane->SetWindowStyleFlag(m_pInfoPane->GetWindowStyleFlag() | wxAUI_NB_BOTTOM);
1518 }
1519
LoadWindowSize()1520 void MainFrame::LoadWindowSize()
1521 {
1522 #ifndef __WXMAC__
1523 int x = 0;
1524 int y = 0;
1525 #else
1526 int x = 0;
1527 int y = wxSystemSettings::GetMetric(wxSYS_MENU_Y, this); // make sure it doesn't hide under the menu bar
1528 #endif
1529 int w = 1000;
1530 int h = 800;
1531
1532 // obtain display index used last time
1533 int last_display_index = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/display"), 0);
1534 // load window size and position
1535 wxRect rect(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left"), x),
1536 Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/top"), y),
1537 Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/width"), w),
1538 Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/height"), h));
1539 // maximize if needed
1540 bool maximized = Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/main_frame/layout/maximized"), true);
1541 Maximize(maximized); // toggle
1542
1543 // set display, size and position
1544 int display_index_window = wxDisplay::GetFromWindow(this); // C::B usually starts on primary display...
1545 // ...but try to use display that was used last time, if still available:
1546 if ((last_display_index>=0) && (last_display_index<static_cast<int>(wxDisplay::GetCount())))
1547 display_index_window = static_cast<int>(last_display_index);
1548 int display_index = ((display_index_window>=0) ? display_index_window : 0);
1549
1550 wxDisplay disp(display_index); // index might be wxNOT_FOUND (=-1) due to GetFromWindow call
1551 if (maximized)
1552 {
1553 rect = disp.GetClientArea(); // apply from display, overriding settings above
1554 rect.width -= 100;
1555 rect.height -= 100;
1556 }
1557 else
1558 {
1559 // Adjust to actual screen size. This is useful for portable C::B versions,
1560 // where the window might be out of screen when saving on a two-monitor
1561 // system an re-opening on a one-monitor system (on Windows, at least).
1562 wxRect displayRect = disp.GetClientArea();
1563 if ((displayRect.GetLeft() + displayRect.GetWidth()) < rect.GetLeft()) rect.SetLeft (displayRect.GetLeft() );
1564 if ((displayRect.GetLeft() + displayRect.GetWidth()) < rect.GetRight()) rect.SetRight (displayRect.GetRight() );
1565 if ((displayRect.GetTop() + displayRect.GetHeight()) < rect.GetTop()) rect.SetTop (displayRect.GetTop() );
1566 if ((displayRect.GetTop() + displayRect.GetHeight()) < rect.GetBottom()) rect.SetBottom(displayRect.GetBottom());
1567 }
1568
1569 SetSize(rect);
1570 }
1571
SaveWindowState()1572 void MainFrame::SaveWindowState()
1573 {
1574 DoCheckCurrentLayoutForChanges(false);
1575
1576 // first delete all previous layouts, otherwise they might remain
1577 // if the new amount of layouts is less than the previous, because only the first layouts will be overwritten
1578 wxArrayString subs = Manager::Get()->GetConfigManager(_T("app"))->EnumerateSubPaths(_T("/main_frame/layout"));
1579 for (size_t i = 0; i < subs.GetCount(); ++i)
1580 {
1581 Manager::Get()->GetConfigManager(_T("app"))->DeleteSubPath(_T("/main_frame/layout/") + subs[i]);
1582 }
1583
1584 int count = 0;
1585 for (LayoutViewsMap::iterator it = m_LayoutViews.begin(); it != m_LayoutViews.end(); ++it)
1586 {
1587 if (it->first.IsEmpty())
1588 continue;
1589 ++count;
1590 wxString key = wxString::Format(_T("/main_frame/layout/view%d/"), count);
1591 Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("name"), it->first);
1592 Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("data"), it->second);
1593
1594 if (!m_LayoutMessagePane[it->first].IsEmpty())
1595 Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("dataMessagePane"), m_LayoutMessagePane[it->first]);
1596 }
1597
1598 // save manager and messages selected page
1599 if (m_pPrjManUI->GetNotebook())
1600 {
1601 int selection = m_pPrjManUI->GetNotebook()->GetSelection();
1602 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/left_block_selection"), selection);
1603 }
1604 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/bottom_block_selection"), m_pInfoPane->GetSelection());
1605
1606 // save display, window size and position
1607 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/display"), wxDisplay::GetFromWindow(this));
1608 if (!IsMaximized() && !IsIconized())
1609 {
1610 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/left"), GetPosition().x);
1611 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/top"), GetPosition().y);
1612 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/width"), GetSize().x);
1613 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/height"), GetSize().y);
1614 }
1615 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/maximized"), IsMaximized());
1616 }
1617
LoadViewLayout(const wxString & name,bool isTemp)1618 void MainFrame::LoadViewLayout(const wxString& name, bool isTemp)
1619 {
1620 if (m_LastLayoutName != name && !DoCheckCurrentLayoutForChanges(true))
1621 return;
1622
1623 m_LastLayoutIsTemp = isTemp;
1624
1625 wxString layout = m_LayoutViews[name];
1626 wxString layoutMP = m_LayoutMessagePane[name];
1627 if (layoutMP.IsEmpty())
1628 layoutMP = m_LayoutMessagePane[gDefaultLayout];
1629 if (layout.IsEmpty())
1630 {
1631 layout = m_LayoutViews[gDefaultLayout];
1632 SaveViewLayout(name, layout, layoutMP, false);
1633 DoSelectLayout(name);
1634 }
1635 else
1636 DoSelectLayout(name);
1637
1638 // first load taborder of MessagePane, so LoadPerspective can restore the last selected tab
1639 m_pInfoPane->LoadTabOrder(layoutMP);
1640
1641 // We have to force an update here, because the m_LayoutManager.GetAllPanes()
1642 // would not report correct values if not updated here.
1643 m_LayoutManager.LoadPerspective(layout, true);
1644
1645 // If we load a layout we have to check if the window is on a valid display
1646 // and has valid size. This can happen if a user moves a layout file from a
1647 // multi display setup to a single display setup. The size has to be checked
1648 // because it is possible that the target display has a lower resolution then
1649 // the source display.
1650 const wxAuiPaneInfoArray& windowArray = m_LayoutManager.GetAllPanes();
1651 for (size_t i = 0; i < windowArray.GetCount(); ++i)
1652 {
1653 cbFixWindowSizeAndPlace(windowArray.Item(i).frame);
1654 }
1655
1656 DoUpdateLayout();
1657
1658 m_PreviousLayoutName = m_LastLayoutName;
1659 m_LastLayoutName = name;
1660 m_LastLayoutData = layout;
1661 m_LastMessagePaneLayoutData = layoutMP;
1662
1663 CodeBlocksLayoutEvent evt(cbEVT_SWITCHED_VIEW_LAYOUT);
1664 evt.layout = name;
1665 Manager::Get()->ProcessEvent(evt);
1666 }
1667
SaveViewLayout(const wxString & name,const wxString & layout,const wxString & layoutMP,bool select)1668 void MainFrame::SaveViewLayout(const wxString& name, const wxString& layout, const wxString& layoutMP, bool select)
1669 {
1670 if (name.IsEmpty())
1671 return;
1672 m_LayoutViews[name] = layout;
1673 m_LayoutMessagePane[name] = layoutMP;
1674 wxMenu* viewLayouts = nullptr;
1675 GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
1676 if (viewLayouts && viewLayouts->FindItem(name) == wxNOT_FOUND)
1677 {
1678 int id = wxNewId();
1679 viewLayouts->InsertCheckItem(viewLayouts->GetMenuItemCount() - 3, id, name, wxString::Format(_("Switch to %s perspective"), name.wx_str()));
1680 Connect( id, wxEVT_COMMAND_MENU_SELECTED,
1681 (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnViewLayout);
1682 m_PluginIDsMap[id] = name;
1683 }
1684 if (select)
1685 {
1686 DoSelectLayout(name);
1687 m_LastLayoutName = name;
1688 }
1689 }
1690
LayoutDifferent(const wxString & layout1,const wxString & layout2,const wxString & delimiter)1691 bool MainFrame::LayoutDifferent(const wxString& layout1,const wxString& layout2,const wxString& delimiter)
1692 {
1693 wxStringTokenizer strTok;
1694 unsigned long j;
1695
1696 strTok.SetString(layout1, delimiter);
1697 wxArrayString arLayout1;
1698 while(strTok.HasMoreTokens())
1699 {
1700 wxStringTokenizer strTokColon(strTok.GetNextToken(), _T(";"));
1701 while(strTokColon.HasMoreTokens())
1702 {
1703 wxString theToken = strTokColon.GetNextToken();
1704 if (theToken.StartsWith(_T("state=")))
1705 {
1706 theToken=theToken.Right(theToken.Len() - wxString(_T("state=")).Len());
1707 theToken.ToULong(&j);
1708 // we filter out the hidden/show state
1709 theToken=wxString::Format(_("state=%lu"),j & wxAuiPaneInfo::optionHidden);
1710 }
1711 arLayout1.Add(theToken);
1712 }
1713 }
1714
1715 strTok.SetString(layout2, delimiter);
1716 wxArrayString arLayout2;
1717 while(strTok.HasMoreTokens())
1718 {
1719 wxStringTokenizer strTokColon(strTok.GetNextToken(), _T(";"));
1720 while(strTokColon.HasMoreTokens())
1721 {
1722 wxString theToken = strTokColon.GetNextToken();
1723 if (theToken.StartsWith(_T("state=")))
1724 {
1725 theToken=theToken.Right(theToken.Len() - wxString(_T("state=")).Len());
1726 theToken.ToULong(&j);
1727 // we filter out the hidden/show state
1728 theToken=wxString::Format(_("state=%lu"),j & wxAuiPaneInfo::optionHidden);
1729 }
1730 arLayout2.Add(theToken);
1731 }
1732 }
1733
1734 arLayout1.Sort();
1735 arLayout2.Sort();
1736
1737 return arLayout1 != arLayout2;
1738 }
1739
LayoutMessagePaneDifferent(const wxString & layout1,const wxString & layout2,bool checkSelection)1740 bool MainFrame::LayoutMessagePaneDifferent(const wxString& layout1,const wxString& layout2, bool checkSelection)
1741 {
1742 wxStringTokenizer strTok;
1743 wxArrayString arLayout1;
1744 wxArrayString arLayout2;
1745
1746 strTok.SetString(layout1.BeforeLast('|'), _T(";"));
1747 while (strTok.HasMoreTokens())
1748 {
1749 arLayout1.Add(strTok.GetNextToken());
1750 }
1751
1752 strTok.SetString(layout2.BeforeLast('|'), _T(";"));
1753 while (strTok.HasMoreTokens())
1754 {
1755 arLayout2.Add(strTok.GetNextToken());
1756 }
1757
1758 if (checkSelection)
1759 {
1760 arLayout1.Add(layout1.AfterLast('|'));
1761 arLayout2.Add(layout2.AfterLast('|'));
1762 }
1763 arLayout1.Sort();
1764 arLayout2.Sort();
1765
1766 return arLayout1 != arLayout2;
1767 }
1768
DoCheckCurrentLayoutForChanges(bool canCancel)1769 bool MainFrame::DoCheckCurrentLayoutForChanges(bool canCancel)
1770 {
1771 DoFixToolbarsLayout();
1772 wxString lastlayout = m_LayoutManager.SavePerspective();
1773 wxString lastmessagepanelayout = m_pInfoPane->SaveTabOrder();
1774 if (!m_LastLayoutName.IsEmpty() &&
1775 (LayoutDifferent(lastlayout, m_LastLayoutData) ||
1776 LayoutMessagePaneDifferent(lastmessagepanelayout, m_LastMessagePaneLayoutData, Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/save_selection_change_in_mp"), true)) ))
1777 {
1778 AnnoyingDialog dlg(_("Layout changed"),
1779 wxString::Format(_("The perspective '%s' has changed. Do you want to save it?"), m_LastLayoutName.wx_str()),
1780 wxART_QUESTION,
1781 canCancel ? AnnoyingDialog::YES_NO_CANCEL : AnnoyingDialog::YES_NO,
1782 // partial fix for bug 18970 (fix is incomplete to prevent the user from saving 'rtCANCEL')
1783 canCancel ? AnnoyingDialog::rtYES : AnnoyingDialog::rtSAVE_CHOICE);
1784 switch (dlg.ShowModal())
1785 {
1786 case AnnoyingDialog::rtYES:
1787 SaveViewLayout(m_LastLayoutName, lastlayout, lastmessagepanelayout, false);
1788 break;
1789 case AnnoyingDialog::rtCANCEL:
1790 DoSelectLayout(m_LastLayoutName);
1791 return false;
1792 default:
1793 break;
1794 }
1795 }
1796 return true;
1797 }
1798
DoFixToolbarsLayout()1799 void MainFrame::DoFixToolbarsLayout()
1800 {
1801 // The AUI layout system remembers toolbar sizes. In most circumstances we don't want this
1802 // feature. So we want to disable it and this is what is done in this function.
1803 // This function has effect after a toolbar size change.
1804 //
1805 // To do it we need to do two passes:
1806 // 1. reset the best/min sizes loaded from the layout file.
1807 // 2. set new best size
1808 //
1809 // The reset operation is needed because wxAUI does nothing when the values for min/best sizes
1810 // aren't equal to wxDefaultSize.
1811 // I'm not really sure why we need the second pass. :(
1812
1813 wxAuiPaneInfoArray &panes = m_LayoutManager.GetAllPanes();
1814 for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1815 {
1816 wxAuiPaneInfo &info = panes[ii];
1817 if (info.IsToolbar() && info.IsShown())
1818 {
1819 info.best_size = wxDefaultSize;
1820 info.min_size = wxDefaultSize;
1821 }
1822 }
1823
1824 // This is needed in order to auto shrink the toolbars to fit the icons with as little space as
1825 // possible.
1826 m_LayoutManager.Update();
1827
1828 for (size_t i = 0; i < panes.GetCount(); ++i)
1829 {
1830 wxAuiPaneInfo& info = panes[i];
1831 if (info.IsToolbar())
1832 {
1833 info.best_size = info.window->GetBestSize();
1834 info.floating_size = wxDefaultSize;
1835 }
1836 }
1837
1838 // If we don't do this toolbars would be empty during initial startup or after
1839 // View -> Perspective -> Save current.
1840 m_LayoutManager.Update();
1841 }
1842
DoSelectLayout(const wxString & name)1843 void MainFrame::DoSelectLayout(const wxString& name)
1844 {
1845 wxMenu* viewLayouts = nullptr;
1846 GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
1847 if (viewLayouts)
1848 {
1849 wxMenuItemList& items = viewLayouts->GetMenuItems();
1850 for (size_t i = 0; i < items.GetCount(); ++i)
1851 {
1852 if (!items[i]->IsCheckable())
1853 continue;
1854 #if wxCHECK_VERSION(3, 0, 0)
1855 items[i]->Check(items[i]->GetItemLabel().IsSameAs(name));
1856 #else
1857 items[i]->Check(items[i]->GetText().IsSameAs(name));
1858 #endif
1859 }
1860
1861 if (!m_LastLayoutIsTemp)
1862 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/default"), name);
1863 }
1864 }
1865
DoAddPluginStatusField(cbPlugin * plugin)1866 void MainFrame::DoAddPluginStatusField(cbPlugin* plugin)
1867 {
1868 cbStatusBar *sbar = (cbStatusBar *)GetStatusBar();
1869 if (!sbar)
1870 return;
1871 plugin->CreateStatusField(sbar);
1872 sbar->AdjustFieldsSize();
1873 }
1874
InitToolbar(wxToolBar * tb)1875 inline void InitToolbar(wxToolBar *tb)
1876 {
1877 tb->SetInitialSize();
1878 }
1879
DoAddPluginToolbar(cbPlugin * plugin)1880 ToolbarInfo MainFrame::DoAddPluginToolbar(cbPlugin* plugin)
1881 {
1882 ToolbarInfo info;
1883 info.toolbar = Manager::Get()->CreateEmptyToolbar();
1884 if (plugin->BuildToolBar(info.toolbar))
1885 {
1886 info.priority = plugin->GetToolBarPriority();
1887 SetToolBar(nullptr);
1888 InitToolbar(info.toolbar);
1889
1890 // add View->Toolbars menu item for toolbar
1891 wxMenu* viewToolbars = nullptr;
1892 GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
1893 if (viewToolbars)
1894 {
1895 wxMenuItem* item = AddPluginInMenus(viewToolbars, plugin,
1896 (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnToggleBar,
1897 -1, true);
1898 if (item)
1899 {
1900 item->Check(true);
1901 m_PluginsTools[plugin] = info.toolbar;
1902 }
1903 }
1904
1905 const PluginInfo* pluginInfo = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1906 if (!pluginInfo)
1907 cbThrow(_T("No plugin info?!?"));
1908
1909 info.paneInfo.Name(pluginInfo->name + _T("Toolbar")).Caption(pluginInfo->title + _(" Toolbar"));
1910 }
1911 else
1912 {
1913 delete info.toolbar;
1914 info.toolbar = nullptr;
1915 }
1916 return info;
1917 }
1918
DoAddPlugin(cbPlugin * plugin)1919 void MainFrame::DoAddPlugin(cbPlugin* plugin)
1920 {
1921 //Manager::Get()->GetLogManager()->DebugLog(_T("Adding plugin: %s"), plugin->GetInfo()->name.wx_str());
1922 AddPluginInHelpPluginsMenu(plugin);
1923 if (plugin->GetType() == ptTool)
1924 {
1925 AddPluginInPluginsMenu(plugin);
1926 }
1927 // offer menu and toolbar space for other plugins
1928 else
1929 {
1930 // menu
1931 try
1932 {
1933 wxMenuBar* mbar = GetMenuBar();
1934 plugin->BuildMenu(mbar);
1935 }
1936 catch (cbException& e)
1937 {
1938 e.ShowErrorMessage();
1939 }
1940 // Don't load the toolbars during the initial loading of the plugins, this code should be executed
1941 // only when a single plugins is loaded from the Plugins -> Manager ... window.
1942 if (!m_ScanningForPlugins)
1943 {
1944 // Create the toolbar for the plugin if there is one.
1945 const ToolbarInfo &toolbarInfo = DoAddPluginToolbar(plugin);
1946 if (toolbarInfo.toolbar)
1947 {
1948 // Place the new toolbar at the bottom of the toolbar pane. Try to reuse the last row
1949 // if there is enough space in it, otherwise place the new toolbar at a new row.
1950 int row = 0;
1951 const wxAuiPaneInfoArray &panes = m_LayoutManager.GetAllPanes();
1952 for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1953 {
1954 const wxAuiPaneInfo &info = panes[ii];
1955 if (info.IsToolbar())
1956 row = std::max(row, info.dock_row);
1957 }
1958 int minX = 100000, maxX = -100000;
1959 int position = 0;
1960 for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1961 {
1962 const wxAuiPaneInfo &info = panes[ii];
1963 if (info.IsToolbar() && info.dock_row == row && info.window)
1964 {
1965 const wxPoint &pt = info.window->GetPosition();
1966 minX = std::min(minX, pt.x + info.window->GetSize().x);
1967 maxX = std::max(maxX, pt.x + info.window->GetSize().x);
1968 position = std::max(position, info.dock_pos);
1969 }
1970 }
1971 if (maxX + toolbarInfo.toolbar->GetSize().x <= GetSize().x)
1972 position++;
1973 else
1974 {
1975 row++;
1976 position = 0;
1977 }
1978 wxAuiPaneInfo paneInfo(toolbarInfo.paneInfo);
1979 m_LayoutManager.AddPane(toolbarInfo.toolbar, paneInfo. ToolbarPane().Top().Row(row).Position(position));
1980 // Add the event handler for mouse right click
1981 toolbarInfo.toolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
1982 wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this);
1983
1984 DoUpdateLayout();
1985 }
1986 }
1987 DoAddPluginStatusField(plugin);
1988 }
1989 }
1990
Open(const wxString & filename,bool addToHistory)1991 bool MainFrame::Open(const wxString& filename, bool addToHistory)
1992 {
1993 wxFileName fn(filename);
1994 fn.Normalize(); // really important so that two same files with different names are not loaded twice
1995 wxString name = fn.GetFullPath();
1996 LogManager *logger = Manager::Get()->GetLogManager();
1997 logger->DebugLog(_T("Opening file ") + name);
1998 bool ret = OpenGeneric(name, addToHistory);
1999 if (!ret)
2000 logger->LogError(wxString::Format(wxT("Opening file '%s' failed!"), name.wx_str()));
2001
2002 return ret;
2003 }
2004
ShowOpenFileDialog(const wxString & caption,const wxString & filter)2005 wxString MainFrame::ShowOpenFileDialog(const wxString& caption, const wxString& filter)
2006 {
2007 wxFileDialog dlg(this,
2008 caption,
2009 wxEmptyString,
2010 wxEmptyString,
2011 filter,
2012 wxFD_OPEN | compatibility::wxHideReadonly);
2013 wxString sel;
2014 PlaceWindow(&dlg);
2015 if (dlg.ShowModal() == wxID_OK)
2016 sel = dlg.GetPath();
2017 return sel;
2018 }
2019
OpenGeneric(const wxString & filename,bool addToHistory)2020 bool MainFrame::OpenGeneric(const wxString& filename, bool addToHistory)
2021 {
2022 if (filename.IsEmpty())
2023 return false;
2024
2025 wxFileName fname(filename); fname.ClearExt(); fname.SetExt(_T("cbp"));
2026 switch ( FileTypeOf(filename) )
2027 {
2028 //
2029 // Workspace
2030 //
2031 case ftCodeBlocksWorkspace:
2032 // verify that it's not the same as the one already open
2033 if (filename == Manager::Get()->GetProjectManager()->GetWorkspace()->GetFilename())
2034 return true;
2035 else
2036 {
2037 if ( DoCloseCurrentWorkspace() )
2038 {
2039 wxBusyCursor wait; // loading a worspace can take some time -> showhourglass
2040 ShowHideStartPage(true); // hide startherepage, so we can use full tab-range
2041 bool ret = Manager::Get()->GetProjectManager()->LoadWorkspace(filename);
2042 if (!ret)
2043 ShowHideStartPage(); // show/hide startherepage, dependant of settings, if loading failed
2044 else if (addToHistory)
2045 m_projectsHistory.AddToHistory(Manager::Get()->GetProjectManager()->GetWorkspace()->GetFilename());
2046 return ret;
2047 }
2048 else
2049 return false;
2050 }
2051 break;
2052
2053 //
2054 // Project
2055 //
2056 case ftCodeBlocksProject:
2057 {
2058 // Make a check whether the project exists in current workspace
2059 cbProject* prj = Manager::Get()->GetProjectManager()->IsOpen(fname.GetFullPath());
2060 if (!prj)
2061 {
2062 wxBusyCursor wait; // loading a workspace can take some time -> showhourglass
2063 return DoOpenProject(filename, addToHistory);
2064 }
2065 else
2066 {
2067 // NOTE (Morten#1#): A message here will prevent batch-builds from working and is shown sometimes even if correct
2068 Manager::Get()->GetProjectManager()->SetProject(prj, false);
2069 return true;
2070 }
2071 }
2072 //
2073 // Source files
2074 //
2075 case ftHeader:
2076 // fallthrough
2077 case ftSource:
2078 // fallthrough
2079 case ftTemplateSource:
2080 // fallthrough
2081 case ftResource:
2082 return DoOpenFile(filename, addToHistory);
2083 //
2084 // For all other files, ask MIME plugin for a suitable handler
2085 //
2086 default:
2087 {
2088 cbMimePlugin* plugin = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile(filename);
2089 // warn user that "Files extension handler" is disabled
2090 if (!plugin)
2091 {
2092 cbMessageBox(_("Could not open file ") + filename + _(",\nbecause no extension handler could be found."), _("Error"), wxICON_ERROR);
2093 return false;
2094 }
2095 if (plugin->OpenFile(filename) == 0)
2096 {
2097 m_filesHistory.AddToHistory(filename);
2098 return true;
2099 }
2100 return false;
2101 }
2102 }
2103 return true;
2104 }
2105
DoOpenProject(const wxString & filename,bool addToHistory)2106 bool MainFrame::DoOpenProject(const wxString& filename, bool addToHistory)
2107 {
2108 // Manager::Get()->GetLogManager()->DebugLog(_T("Opening project '%s'"), filename.wx_str());
2109 if (!wxFileExists(filename))
2110 {
2111 cbMessageBox(_("The project file does not exist..."), _("Error"), wxICON_ERROR);
2112 return false;
2113 }
2114
2115 ShowHideStartPage(true); // hide startherepage, so we can use full tab-range
2116 cbProject* prj = Manager::Get()->GetProjectManager()->LoadProject(filename, true);
2117 if (prj)
2118 {
2119 if (addToHistory)
2120 m_projectsHistory.AddToHistory(prj->GetFilename());
2121 return true;
2122 }
2123 ShowHideStartPage(); // show/hide startherepage, dependant of settings, if loading failed
2124 return false;
2125 }
2126
DoOpenFile(const wxString & filename,bool addToHistory)2127 bool MainFrame::DoOpenFile(const wxString& filename, bool addToHistory)
2128 {
2129 cbEditor* ed = Manager::Get()->GetEditorManager()->Open(filename);
2130 if (ed)
2131 {
2132 // Cryogen 24/3/10 Activate the editor after opening. Partial fix for bug #14087.
2133 ed->Activate();
2134 if (addToHistory)
2135 m_filesHistory.AddToHistory(ed->GetFilename());
2136 return true;
2137 }
2138 return false;
2139 }
2140
DoCloseCurrentWorkspace()2141 bool MainFrame::DoCloseCurrentWorkspace()
2142 {
2143 return Manager::Get()->GetProjectManager()->CloseWorkspace();
2144 }
2145
DoCreateStatusBar()2146 void MainFrame::DoCreateStatusBar()
2147 {
2148 wxClientDC dc(this);
2149 wxFont font = dc.GetFont();
2150 int h;
2151 size_t num = 0;
2152
2153 wxCoord widths[16]; // 16 max
2154 widths[num++] = -1; // main field
2155
2156 dc.GetTextExtent(_(" Highlight Button "), &widths[num++], &h);
2157 dc.GetTextExtent(_(" Windows (CR+LF) "), &widths[num++], &h);
2158 dc.GetTextExtent(_(" WINDOWS-1252 "), &widths[num++], &h);
2159 dc.GetTextExtent(_(" Line 12345, Col 123, Pos 123456 "), &widths[num++], &h);
2160 dc.GetTextExtent(_(" Overwrite "), &widths[num++], &h);
2161 dc.GetTextExtent(_(" Modified "), &widths[num++], &h);
2162 dc.GetTextExtent(_(" Read/Write "), &widths[num++], &h);
2163 dc.GetTextExtent(_(" name_of_profile "), &widths[num++], &h);
2164
2165 wxStatusBar* sb = CreateStatusBar(num);
2166 if (!sb)
2167 return;
2168
2169 SetStatusWidths(num, widths);
2170
2171 // Highlightbutton
2172 wxRect rect;
2173 if (sb->GetFieldRect(1, rect))
2174 {
2175 m_pHighlightButton = new wxButton(sb, idHighlightButton, wxT("bla"), wxDefaultPosition, wxDefaultSize,
2176 wxBORDER_NONE|wxBU_LEFT|wxBU_EXACTFIT);
2177 // Adjust status bar height to fit the button.
2178 // This affects wx3.x build more than wx2.8 builds. At least on wxGTK.
2179 const int height = std::max(sb->GetMinHeight(), m_pHighlightButton->GetClientSize().GetHeight());
2180 sb->SetMinHeight(height);
2181 }
2182 }
2183
2184 /// Change the label of a button only if it has really changed. This is used for status bar button,
2185 /// because if we always set the label there is flickering while scrolling in the editor.
2186 /// I've observed the flickering on wxGTK and I don't know if it is present on the other ports.
changeButtonLabel(wxButton & button,const wxString & text)2187 static void changeButtonLabel(wxButton &button, const wxString &text)
2188 {
2189 if (text != button.GetLabel())
2190 button.SetLabel(text);
2191 }
2192
DoUpdateStatusBar()2193 void MainFrame::DoUpdateStatusBar()
2194 {
2195 if (!GetStatusBar())
2196 return;
2197 if (Manager::IsAppShuttingDown())
2198 return;
2199
2200 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
2201 wxString personality(Manager::Get()->GetPersonalityManager()->GetPersonality());
2202 if (ed)
2203 {
2204 cbStyledTextCtrl * const control = ed->GetControl();
2205
2206 int panel = 0;
2207 int pos = control->GetCurrentPos();
2208 wxString msg;
2209 SetStatusText(ed->GetFilename(), panel++);
2210
2211 // Highlightbutton
2212 if (m_pHighlightButton)
2213 {
2214 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
2215 if (colour_set)
2216 changeButtonLabel(*m_pHighlightButton, colour_set->GetLanguageName(ed->GetLanguage()));
2217 else
2218 changeButtonLabel(*m_pHighlightButton, wxEmptyString);
2219 }
2220 // EOL mode
2221 panel++;
2222 switch (control->GetEOLMode())
2223 {
2224 case wxSCI_EOL_CRLF: msg = _T("Windows (CR+LF)"); break;
2225 case wxSCI_EOL_CR: msg = _T("Mac (CR)"); break;
2226 case wxSCI_EOL_LF: msg = _T("Unix (LF)"); break;
2227 default: break;
2228 }
2229 SetStatusText(msg, panel++);
2230 SetStatusText(ed->GetEncodingName(), panel++);
2231 msg.Printf(_("Line %d, Col %d, Pos %d"), control->GetCurrentLine() + 1, control->GetColumn(pos) + 1, pos);
2232 SetStatusText(msg, panel++);
2233 SetStatusText(control->GetOvertype() ? _("Overwrite") : _("Insert"), panel++);
2234 #if wxCHECK_VERSION(3, 0, 0)
2235 SetStatusText(ed->GetModified() ? _("Modified") : _T(""), panel++);
2236 #else
2237 SetStatusText(ed->GetModified() ? _("Modified") : wxEmptyString, panel++);
2238 #endif
2239 SetStatusText(control->GetReadOnly() ? _("Read only") : _("Read/Write"), panel++);
2240 SetStatusText(personality, panel++);
2241 }
2242 else
2243 {
2244 int panel = 0;
2245 EditorBase *eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
2246 if ( eb )
2247 SetStatusText(eb->GetFilename(), panel++);
2248 else
2249 SetStatusText(_("Welcome to ") + appglobals::AppName + _T("!"), panel++);
2250
2251 // Highlightbutton
2252 if (m_pHighlightButton)
2253 changeButtonLabel(*m_pHighlightButton, wxEmptyString);
2254 panel++;
2255
2256 SetStatusText(wxEmptyString, panel++);
2257 SetStatusText(wxEmptyString, panel++);
2258 SetStatusText(wxEmptyString, panel++);
2259 SetStatusText(wxEmptyString, panel++);
2260 SetStatusText(wxEmptyString, panel++);
2261 SetStatusText(wxEmptyString, panel++);
2262 SetStatusText(personality, panel++);
2263 }
2264 }
2265
DoUpdateEditorStyle(cbAuiNotebook * target,const wxString & prefix,long defaultStyle)2266 void MainFrame::DoUpdateEditorStyle(cbAuiNotebook* target, const wxString& prefix, long defaultStyle)
2267 {
2268 if (!target)
2269 return;
2270
2271 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
2272 target->SetTabCtrlHeight(1);
2273
2274 long nbstyle = cfg->ReadInt(_T("/environment/tabs_style"), 0);
2275 switch (nbstyle)
2276 {
2277 case 1: // simple style
2278 target->SetArtProvider(new wxAuiSimpleTabArt());
2279 break;
2280
2281 case 2: // VC 7.1 style
2282 target->SetArtProvider(new NbStyleVC71());
2283 break;
2284
2285 case 3: // Firefox 2 style
2286 target->SetArtProvider(new NbStyleFF2());
2287 break;
2288
2289 default: // default style
2290 #if defined(__WXGTK__) && (USE_GTK_NOTEBOOK) && !wxCHECK_VERSION(3, 0, 0)
2291 target->SetArtProvider(new NbStyleGTK());
2292 #else
2293 target->SetArtProvider(new wxAuiDefaultTabArt());
2294 #endif
2295 break;
2296 }
2297
2298 target->SetTabCtrlHeight(-1);
2299
2300 nbstyle = defaultStyle;
2301 if (cfg->ReadBool(_T("/environment/") + prefix + _T("_tabs_bottom")))
2302 nbstyle |= wxAUI_NB_BOTTOM;
2303
2304 if (cfg->ReadBool(_T("/environment/tabs_list")))
2305 nbstyle |= wxAUI_NB_WINDOWLIST_BUTTON;
2306
2307 target->SetWindowStyleFlag(nbstyle);
2308 }
2309
DoUpdateEditorStyle()2310 void MainFrame::DoUpdateEditorStyle()
2311 {
2312 long style = wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_MIDDLE_CLICK_CLOSE;
2313 long closestyle = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/environment/tabs_closestyle"), 0);
2314 switch (closestyle)
2315 {
2316 case 1: // current tab
2317 style |= wxAUI_NB_CLOSE_ON_ACTIVE_TAB;
2318 break;
2319
2320 case 2: // right side
2321 style |= wxAUI_NB_CLOSE_BUTTON;
2322 break;
2323
2324 default: // all tabs (default)
2325 style |= wxAUI_NB_CLOSE_ON_ALL_TABS;
2326 break;
2327 }
2328
2329 cbAuiNotebook* an = Manager::Get()->GetEditorManager()->GetNotebook();
2330
2331 DoUpdateEditorStyle(an, _T("editor"), style | wxNO_FULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN);
2332 if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/hide_editor_tabs"),false))
2333 an->SetTabCtrlHeight(0);
2334
2335 an = m_pInfoPane;
2336 DoUpdateEditorStyle(an, _T("infopane"), style);
2337
2338 an = m_pPrjManUI->GetNotebook();
2339 DoUpdateEditorStyle(an, _T("project"), wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_TAB_MOVE);
2340 }
2341
DoUpdateLayoutColours()2342 void MainFrame::DoUpdateLayoutColours()
2343 {
2344 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
2345 wxAuiDockArt* art = m_LayoutManager.GetArtProvider();
2346
2347 #ifndef __WXGTK__
2348 m_LayoutManager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_ALLOW_ACTIVE_PANE | wxAUI_MGR_TRANSPARENT_DRAG);
2349 #else // #ifndef __WXGTK__
2350 // workaround for a wxWidgets-bug that makes C::B crash when a floating window gets docked and composite-effects are enabled
2351 m_LayoutManager.SetFlags((wxAUI_MGR_DEFAULT | wxAUI_MGR_ALLOW_ACTIVE_PANE | wxAUI_MGR_TRANSPARENT_DRAG | wxAUI_MGR_VENETIAN_BLINDS_HINT)& ~wxAUI_MGR_TRANSPARENT_HINT);
2352 #endif // #ifndef __WXGTK__
2353
2354 art->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, cfg->ReadInt(_T("/environment/aui/border_size"), art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE)));
2355 art->SetMetric(wxAUI_DOCKART_SASH_SIZE, cfg->ReadInt(_T("/environment/aui/sash_size"), art->GetMetric(wxAUI_DOCKART_SASH_SIZE)));
2356 art->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, cfg->ReadInt(_T("/environment/aui/caption_size"), art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE)));
2357 art->SetColour(wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR, cfg->ReadColour(_T("/environment/aui/active_caption_colour"), art->GetColour(wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR)));
2358 art->SetColour(wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR, cfg->ReadColour(_T("/environment/aui/active_caption_gradient_colour"), art->GetColour(wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR)));
2359 art->SetColour(wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR, cfg->ReadColour(_T("/environment/aui/active_caption_text_colour"), art->GetColour(wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR)));
2360 art->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, cfg->ReadColour(_T("/environment/aui/inactive_caption_colour"), art->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR)));
2361 art->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR, cfg->ReadColour(_T("/environment/aui/inactive_caption_gradient_colour"), art->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR)));
2362 art->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR, cfg->ReadColour(_T("/environment/aui/inactive_caption_text_colour"), art->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR)));
2363
2364 DoUpdateLayout();
2365 }
2366
DoUpdateLayout()2367 void MainFrame::DoUpdateLayout()
2368 {
2369 if (!m_StartupDone)
2370 return;
2371
2372 DoFixToolbarsLayout();
2373 }
2374
DoUpdateAppTitle()2375 void MainFrame::DoUpdateAppTitle()
2376 {
2377 EditorBase* ed = Manager::Get()->GetEditorManager() ? Manager::Get()->GetEditorManager()->GetActiveEditor() : nullptr;
2378 cbProject* prj = nullptr;
2379 if (ed && ed->IsBuiltinEditor())
2380 {
2381 ProjectFile* prjf = ((cbEditor*)ed)->GetProjectFile();
2382 if (prjf)
2383 prj = prjf->GetParentProject();
2384 }
2385 else
2386 prj = Manager::Get()->GetProjectManager() ? Manager::Get()->GetProjectManager()->GetActiveProject() : nullptr;
2387 wxString projname;
2388 wxString edname;
2389 wxString fulltitle;
2390 if (ed || prj)
2391 {
2392 if (prj)
2393 {
2394 if (Manager::Get()->GetProjectManager()->GetActiveProject() == prj)
2395 projname = wxString(_T(" [")) + prj->GetTitle() + _T("]");
2396 else
2397 projname = wxString(_T(" (")) + prj->GetTitle() + _T(")");
2398 }
2399 if (ed)
2400 edname = ed->GetTitle();
2401 fulltitle = edname + projname;
2402 if (!fulltitle.IsEmpty())
2403 fulltitle.Append(_T(" - "));
2404 }
2405 fulltitle.Append(appglobals::AppName);
2406 fulltitle.Append(_T(" "));
2407 fulltitle.Append(appglobals::AppVersion);
2408 SetTitle(fulltitle);
2409 }
2410
ShowHideStartPage(bool forceHasProject,int forceState)2411 void MainFrame::ShowHideStartPage(bool forceHasProject, int forceState)
2412 {
2413 // Manager::Get()->GetLogManager()->LogWarning(_("Toggling start page"));
2414 if (Manager::IsBatchBuild())
2415 return;
2416
2417 // we use the 'forceHasProject' param because when a project is opened
2418 // the EVT_PROJECT_OPEN event is fired *before* ProjectManager::GetProjects()
2419 // and ProjectManager::GetActiveProject() are updated...
2420
2421 if (m_InitiatedShutdown)
2422 {
2423 EditorBase* sh = Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle);
2424 if (sh)
2425 sh->Destroy();
2426 return;
2427 }
2428
2429 bool show = !forceHasProject &&
2430 Manager::Get()->GetProjectManager()->GetProjects()->GetCount() == 0 &&
2431 Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/start_here_page"), true);
2432
2433 if (forceState<0)
2434 show = false;
2435 if (forceState>0)
2436 show = true;
2437
2438 EditorBase* sh = Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle);
2439 if (show)
2440 {
2441 if (!sh)
2442 {
2443 sh = new StartHerePage(this, m_projectsHistory, m_filesHistory,
2444 Manager::Get()->GetEditorManager()->GetNotebook());
2445 }
2446 else
2447 static_cast<StartHerePage*>(sh)->Reload();
2448 }
2449 else if (!show && sh)
2450 sh->Destroy();
2451
2452 DoUpdateAppTitle();
2453 }
2454
ShowHideScriptConsole()2455 void MainFrame::ShowHideScriptConsole()
2456 {
2457 if (Manager::IsBatchBuild())
2458 return;
2459 bool isVis = IsWindowReallyShown(m_pScriptConsole);
2460 CodeBlocksDockEvent evt(isVis ? cbEVT_HIDE_DOCK_WINDOW : cbEVT_SHOW_DOCK_WINDOW);
2461 evt.pWindow = m_pScriptConsole;
2462 Manager::Get()->ProcessEvent(evt);
2463 }
2464
OnStartHereLink(wxCommandEvent & event)2465 void MainFrame::OnStartHereLink(wxCommandEvent& event)
2466 {
2467 wxCommandEvent evt;
2468 evt.SetId(idFileNewProject);
2469 wxString link = event.GetString();
2470 if (link.IsSameAs(_T("CB_CMD_NEW_PROJECT")))
2471 OnFileNewWhat(evt);
2472 else if (link.IsSameAs(_T("CB_CMD_OPEN_PROJECT")))
2473 DoOnFileOpen(true);
2474 // else if (link.IsSameAs(_T("CB_CMD_CONF_ENVIRONMENT")))
2475 // OnSettingsEnvironment(evt);
2476 // else if (link.IsSameAs(_T("CB_CMD_CONF_EDITOR")))
2477 // Manager::Get()->GetEditorManager()->Configure();
2478 // else if (link.IsSameAs(_T("CB_CMD_CONF_COMPILER")))
2479 // OnSettingsCompilerDebugger(evt);
2480 else if (link.StartsWith(_T("CB_CMD_OPEN_HISTORY_")))
2481 {
2482 RecentItemsList *recent;
2483 recent = link.StartsWith(_T("CB_CMD_OPEN_HISTORY_PROJECT_")) ? &m_projectsHistory : &m_filesHistory;
2484 unsigned long item;
2485 link.AfterLast(_T('_')).ToULong(&item);
2486 --item;
2487 const wxString &filename = recent->GetHistoryFile(item);
2488 if (!filename.empty())
2489 {
2490 if ( !OpenGeneric(filename, true) )
2491 recent->AskToRemoveFileFromHistory(item);
2492 }
2493 }
2494 else if (link.StartsWith(_T("CB_CMD_DELETE_HISTORY_")))
2495 {
2496 RecentItemsList *recent;
2497 recent = link.StartsWith(_T("CB_CMD_DELETE_HISTORY_PROJECT_")) ? &m_projectsHistory : &m_filesHistory;
2498 unsigned long item;
2499 link.AfterLast(_T('_')).ToULong(&item);
2500 --item;
2501 recent->AskToRemoveFileFromHistory(item, false);
2502 }
2503 else if (link.IsSameAs(_T("CB_CMD_TIP_OF_THE_DAY")))
2504 ShowTips(true);
2505 }
2506
InitializeRecentFilesHistory()2507 void MainFrame::InitializeRecentFilesHistory()
2508 {
2509 m_filesHistory.Initialize();
2510 m_projectsHistory.Initialize();
2511 }
2512
TerminateRecentFilesHistory()2513 void MainFrame::TerminateRecentFilesHistory()
2514 {
2515 m_filesHistory.TerminateHistory();
2516 m_projectsHistory.TerminateHistory();
2517 }
2518
GetEditorDescription(EditorBase * eb)2519 wxString MainFrame::GetEditorDescription(EditorBase* eb)
2520 {
2521 wxString descr = wxEmptyString;
2522 cbProject* prj = NULL;
2523 if (eb && eb->IsBuiltinEditor())
2524 {
2525 ProjectFile* prjf = ((cbEditor*)eb)->GetProjectFile();
2526 if (prjf)
2527 prj = prjf->GetParentProject();
2528 }
2529 else
2530 prj = Manager::Get()->GetProjectManager() ? Manager::Get()->GetProjectManager()->GetActiveProject() : nullptr;
2531 if (prj)
2532 {
2533 descr = wxString(_("Project: ")) + _T("<b>") + prj->GetTitle() + _T("</b>");
2534 if (Manager::Get()->GetProjectManager()->GetActiveProject() == prj)
2535 descr += wxString(_(" (Active)"));
2536 descr += wxString(_T("<br>"));
2537 }
2538 if (eb)
2539 descr += eb->GetFilename();
2540 return descr;
2541 }
2542
2543 ////////////////////////////////////////////////////////////////////////////////
2544 // event handlers
2545 ////////////////////////////////////////////////////////////////////////////////
2546
OnPluginsExecuteMenu(wxCommandEvent & event)2547 void MainFrame::OnPluginsExecuteMenu(wxCommandEvent& event)
2548 {
2549 wxString pluginName = m_PluginIDsMap[event.GetId()];
2550 if (!pluginName.IsEmpty())
2551 Manager::Get()->GetPluginManager()->ExecutePlugin(pluginName);
2552 else
2553 Manager::Get()->GetLogManager()->DebugLog(F(_T("No plugin found for ID %d"), event.GetId()));
2554 }
2555
OnHelpPluginMenu(wxCommandEvent & event)2556 void MainFrame::OnHelpPluginMenu(wxCommandEvent& event)
2557 {
2558 wxString pluginName = m_PluginIDsMap[event.GetId()];
2559 if (!pluginName.IsEmpty())
2560 {
2561 const PluginInfo* pi = Manager::Get()->GetPluginManager()->GetPluginInfo(pluginName);
2562 if (!pi)
2563 {
2564 Manager::Get()->GetLogManager()->DebugLog(_T("No plugin info for ") + pluginName);
2565 return;
2566 }
2567 dlgAboutPlugin dlg(this, pi);
2568 PlaceWindow(&dlg);
2569 dlg.ShowModal();
2570 }
2571 else
2572 Manager::Get()->GetLogManager()->DebugLog(F(_T("No plugin found for ID %d"), event.GetId()));
2573 }
2574
OnFileNewWhat(wxCommandEvent & event)2575 void MainFrame::OnFileNewWhat(wxCommandEvent& event)
2576 {
2577 int id = event.GetId();
2578 if (id != idFileNewEmpty)
2579 {
2580 // wizard-based
2581
2582 TemplateOutputType tot = totProject;
2583 if (id == idFileNewProject) tot = totProject;
2584 else if (id == idFileNewTarget) tot = totTarget;
2585 else if (id == idFileNewFile) tot = totFiles;
2586 else if (id == idFileNewCustom) tot = totCustom;
2587 else if (id == idFileNewUser) tot = totUser;
2588 else return;
2589
2590 wxString filename;
2591 cbProject* prj = TemplateManager::Get()->New(tot, &filename);
2592 // verify that the open files are still in sync
2593 // the new file might have overwritten an existing one)
2594 Manager::Get()->GetEditorManager()->CheckForExternallyModifiedFiles();
2595
2596 // If both are empty it means that the wizard has failed
2597 if (!prj && filename.IsEmpty())
2598 return;
2599
2600 // Send the new project event
2601 CodeBlocksEvent evtNew(cbEVT_PROJECT_NEW, 0, prj);
2602 Manager::Get()->GetPluginManager()->NotifyPlugins(evtNew);
2603
2604 if (prj)
2605 {
2606 prj->Save();
2607 prj->SaveAllFiles();
2608 }
2609
2610 if (!filename.IsEmpty())
2611 {
2612 if (prj)
2613 m_projectsHistory.AddToHistory(filename);
2614 else
2615 m_filesHistory.AddToHistory(filename);
2616 }
2617 if (prj && tot == totProject) // Created project should be parsed
2618 {
2619 CodeBlocksEvent evtOpen(cbEVT_PROJECT_OPEN, 0, prj);
2620 Manager::Get()->GetPluginManager()->NotifyPlugins(evtOpen);
2621 }
2622 return;
2623 }
2624
2625 // new empty file quick shortcut code below
2626
2627 cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
2628 if (project)
2629 wxSetWorkingDirectory(project->GetBasePath());
2630 cbEditor* ed = Manager::Get()->GetEditorManager()->New();
2631
2632 // initially start change-collection if configured on empty files
2633 if (ed)
2634 ed->GetControl()->SetChangeCollection(Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true));
2635
2636 if (ed && ed->IsOK())
2637 m_filesHistory.AddToHistory(ed->GetFilename());
2638
2639 if (!ed || !project)
2640 return;
2641
2642 wxString oldname = ed->GetFilename();
2643 if (cbMessageBox(_("Do you want to add this new file in the active project (has to be saved first)?"),
2644 _("Add file to project"),
2645 wxYES_NO | wxICON_QUESTION) == wxID_YES &&
2646 ed->SaveAs() && ed->IsOK())
2647 {
2648 wxArrayInt targets;
2649 if (Manager::Get()->GetProjectManager()->AddFileToProject(ed->GetFilename(), project, targets) != 0)
2650 {
2651 ProjectFile* pf = project->GetFileByFilename(ed->GetFilename(), false);
2652 ed->SetProjectFile(pf);
2653 m_pPrjManUI->RebuildTree();
2654 }
2655 }
2656 // verify that the open files are still in sync
2657 // the new file might have overwritten an existing one)
2658 Manager::Get()->GetEditorManager()->CheckForExternallyModifiedFiles();
2659 }
2660
OnDropFiles(wxCoord,wxCoord,const wxArrayString & files)2661 bool MainFrame::OnDropFiles(wxCoord /*x*/, wxCoord /*y*/, const wxArrayString& files)
2662 {
2663 bool success = true; // Safe case initialisation
2664
2665 // first check to see if a workspace is passed. If so, only this will be loaded
2666 wxString foundWorkspace;
2667 for (unsigned int i = 0; i < files.GetCount(); ++i)
2668 {
2669 FileType ft = FileTypeOf(files[i]);
2670 if (ft == ftCodeBlocksWorkspace || ft == ftMSVC6Workspace || ft == ftMSVC7Workspace)
2671 {
2672 foundWorkspace = files[i];
2673 break;
2674 }
2675 }
2676
2677 if (!foundWorkspace.IsEmpty())
2678 success &= OpenGeneric(foundWorkspace);
2679 else
2680 {
2681 wxBusyCursor useless;
2682 wxPaintEvent e;
2683 ProcessEvent(e);
2684 for (unsigned int i = 0; i < files.GetCount(); ++i)
2685 success &= OpenGeneric(files[i]);
2686 }
2687 return success;
2688 }
2689
OnFileNew(cb_unused wxCommandEvent & event)2690 void MainFrame::OnFileNew(cb_unused wxCommandEvent& event)
2691 {
2692 wxMenu* popup = nullptr;
2693 wxMenuBar* bar = GetMenuBar();
2694 if (!bar)
2695 return;
2696
2697 bar->FindItem(idFileNewProject, &popup);
2698 if (popup)
2699 {
2700 popup = CopyMenu(popup);
2701 if (popup)
2702 {
2703 PopupMenu(popup); // this will lead us in OnFileNewWhat() - the meat is there ;)
2704 delete popup;
2705 }
2706 }
2707 }
2708
2709 // in case we are opening a project (bProject == true) we do not want to interfere
2710 // with 'last type of files' (probably the call was open (existing) project on the
2711 // start here page --> so we know it's a project --> set the filter accordingly
2712 // but as said don't force the 'last used type of files' to change, that should
2713 // only change when an open file is carried out (so (source) file <---> project (file) )
2714 // TODO : when regular file open and user manually sets filter to project files --> will change
2715 // the last type : is that expected behaviour ???
DoOnFileOpen(bool bProject)2716 void MainFrame::DoOnFileOpen(bool bProject)
2717 {
2718 wxString Filters = FileFilters::GetFilterString();
2719 // the value returned by GetIndexForFilterAll() is updated by GetFilterString()
2720 int StoredIndex = FileFilters::GetIndexForFilterAll();
2721 wxString Path;
2722 ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("app"));
2723 if (mgr)
2724 {
2725 if (!bProject)
2726 {
2727 wxString Filter = mgr->Read(_T("/file_dialogs/file_new_open/filter"));
2728 if (!Filter.IsEmpty())
2729 FileFilters::GetFilterIndexFromName(Filters, Filter, StoredIndex);
2730 Path = mgr->Read(_T("/file_dialogs/file_new_open/directory"), Path);
2731 }
2732 else
2733 FileFilters::GetFilterIndexFromName(Filters, _("Code::Blocks project/workspace files"), StoredIndex);
2734 }
2735 wxFileDialog dlg(this,
2736 _("Open file"),
2737 Path,
2738 wxEmptyString,
2739 Filters,
2740 wxFD_OPEN | wxFD_MULTIPLE | compatibility::wxHideReadonly);
2741 dlg.SetFilterIndex(StoredIndex);
2742
2743 PlaceWindow(&dlg);
2744 if (dlg.ShowModal() == wxID_OK)
2745 {
2746 // store the last used filter and directory
2747 // as said : don't do this in case of an 'open project'
2748 if (mgr && !bProject)
2749 {
2750 int Index = dlg.GetFilterIndex();
2751 wxString Filter;
2752 if (FileFilters::GetFilterNameFromIndex(Filters, Index, Filter))
2753 mgr->Write(_T("/file_dialogs/file_new_open/filter"), Filter);
2754 wxString Test = dlg.GetDirectory();
2755 mgr->Write(_T("/file_dialogs/file_new_open/directory"), dlg.GetDirectory());
2756 }
2757 wxArrayString files;
2758 dlg.GetPaths(files);
2759 OnDropFiles(0,0,files);
2760 }
2761 }
2762
OnFileOpen(cb_unused wxCommandEvent & event)2763 void MainFrame::OnFileOpen(cb_unused wxCommandEvent& event)
2764 {
2765 DoOnFileOpen(false); // through file menu (not sure if we are opening a project)
2766 }
2767
OnFileReopenProject(wxCommandEvent & event)2768 void MainFrame::OnFileReopenProject(wxCommandEvent& event)
2769 {
2770 size_t id = event.GetId() - wxID_CBFILE17;
2771 wxString fname = m_projectsHistory.GetHistoryFile(id);
2772 if (!OpenGeneric(fname, true))
2773 m_projectsHistory.AskToRemoveFileFromHistory(id);
2774 }
2775
OnFileOpenRecentProjectClearHistory(cb_unused wxCommandEvent & event)2776 void MainFrame::OnFileOpenRecentProjectClearHistory(cb_unused wxCommandEvent& event)
2777 {
2778 m_projectsHistory.ClearHistory();
2779 }
2780
OnFileReopen(wxCommandEvent & event)2781 void MainFrame::OnFileReopen(wxCommandEvent& event)
2782 {
2783 size_t id = event.GetId() - wxID_CBFILE01;
2784 wxString fname = m_filesHistory.GetHistoryFile(id);
2785 if (!OpenGeneric(fname, true))
2786 m_filesHistory.AskToRemoveFileFromHistory(id);
2787 }
2788
OnFileOpenRecentClearHistory(cb_unused wxCommandEvent & event)2789 void MainFrame::OnFileOpenRecentClearHistory(cb_unused wxCommandEvent& event)
2790 {
2791 m_filesHistory.ClearHistory();
2792 }
2793
OnFileSave(cb_unused wxCommandEvent & event)2794 void MainFrame::OnFileSave(cb_unused wxCommandEvent& event)
2795 {
2796 if (!Manager::Get()->GetEditorManager()->SaveActive())
2797 {
2798 wxString msg;
2799 msg.Printf(_("File %s could not be saved..."), Manager::Get()->GetEditorManager()->GetActiveEditor()->GetFilename().wx_str());
2800 cbMessageBox(msg, _("Error saving file"), wxICON_ERROR);
2801 }
2802 DoUpdateStatusBar();
2803 }
2804
OnFileSaveAs(cb_unused wxCommandEvent & event)2805 void MainFrame::OnFileSaveAs(cb_unused wxCommandEvent& event)
2806 {
2807 Manager::Get()->GetEditorManager()->SaveActiveAs();
2808 DoUpdateStatusBar();
2809 }
2810
OnFileSaveProject(cb_unused wxCommandEvent & event)2811 void MainFrame::OnFileSaveProject(cb_unused wxCommandEvent& event)
2812 {
2813 // no need to call SaveActiveProjectAs(), because this is handled in cbProject::Save()
2814 ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2815 if (prjManager->SaveActiveProject())
2816 m_projectsHistory.AddToHistory(prjManager->GetActiveProject()->GetFilename());
2817 DoUpdateStatusBar();
2818 DoUpdateAppTitle();
2819 }
2820
OnFileSaveProjectAs(cb_unused wxCommandEvent & event)2821 void MainFrame::OnFileSaveProjectAs(cb_unused wxCommandEvent& event)
2822 {
2823 ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2824 if (prjManager->SaveActiveProjectAs())
2825 m_projectsHistory.AddToHistory(prjManager->GetActiveProject()->GetFilename());
2826 DoUpdateStatusBar();
2827 DoUpdateAppTitle();
2828 }
2829
OnFileSaveAll(cb_unused wxCommandEvent & event)2830 void MainFrame::OnFileSaveAll(cb_unused wxCommandEvent& event)
2831 {
2832 Manager::Get()->GetConfigManager(_T("app"))->Flush();
2833 Manager::Get()->GetEditorManager()->SaveAll();
2834 ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2835 prjManager->SaveAllProjects();
2836
2837 if (prjManager->GetWorkspace()->GetModified()
2838 && !prjManager->GetWorkspace()->IsDefault()
2839 && prjManager->SaveWorkspace())
2840 {
2841 m_projectsHistory.AddToHistory(prjManager->GetWorkspace()->GetFilename());
2842 }
2843 DoUpdateStatusBar();
2844 DoUpdateAppTitle();
2845 }
2846
OnFileSaveProjectTemplate(cb_unused wxCommandEvent & event)2847 void MainFrame::OnFileSaveProjectTemplate(cb_unused wxCommandEvent& event)
2848 {
2849 TemplateManager::Get()->SaveUserTemplate(Manager::Get()->GetProjectManager()->GetActiveProject());
2850 }
2851
OnFileCloseProject(cb_unused wxCommandEvent & event)2852 void MainFrame::OnFileCloseProject(cb_unused wxCommandEvent& event)
2853 {
2854 // we 're not actually shutting down here, but we want to check if the
2855 // active project is still opening files (still busy)
2856 if (!ProjectManager::CanShutdown() || !EditorManager::CanShutdown())
2857 {
2858 wxBell();
2859 return;
2860 }
2861 Manager::Get()->GetProjectManager()->CloseActiveProject();
2862 DoUpdateStatusBar();
2863 }
2864
OnFileImportProjectDevCpp(cb_unused wxCommandEvent & event)2865 void MainFrame::OnFileImportProjectDevCpp(cb_unused wxCommandEvent& event)
2866 {
2867 OpenGeneric(ShowOpenFileDialog(_("Import Dev-C++ project"), FileFilters::GetFilterString(_T('.') + FileFilters::DEVCPP_EXT)), false);
2868 }
2869
OnFileImportProjectMSVC(cb_unused wxCommandEvent & event)2870 void MainFrame::OnFileImportProjectMSVC(cb_unused wxCommandEvent& event)
2871 {
2872 OpenGeneric(ShowOpenFileDialog(_("Import MS Visual C++ 6.0 project"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC6_EXT)), false);
2873 }
2874
OnFileImportProjectMSVCWksp(cb_unused wxCommandEvent & event)2875 void MainFrame::OnFileImportProjectMSVCWksp(cb_unused wxCommandEvent& event)
2876 {
2877 OpenGeneric(ShowOpenFileDialog(_("Import MS Visual C++ 6.0 workspace"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC6_WORKSPACE_EXT)), false);
2878 }
2879
OnFileImportProjectMSVS(cb_unused wxCommandEvent & event)2880 void MainFrame::OnFileImportProjectMSVS(cb_unused wxCommandEvent& event)
2881 {
2882 OpenGeneric(ShowOpenFileDialog(_("Import MS Visual Studio 7.0+ project"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC7_EXT)), false);
2883 }
2884
OnFileImportProjectMSVSWksp(cb_unused wxCommandEvent & event)2885 void MainFrame::OnFileImportProjectMSVSWksp(cb_unused wxCommandEvent& event)
2886 {
2887 OpenGeneric(ShowOpenFileDialog(_("Import MS Visual Studio 7.0+ solution"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC7_WORKSPACE_EXT)), false);
2888 }
2889
OnFileOpenDefWorkspace(cb_unused wxCommandEvent & event)2890 void MainFrame::OnFileOpenDefWorkspace(cb_unused wxCommandEvent& event)
2891 {
2892 ProjectManager *pman = Manager::Get()->GetProjectManager();
2893 if (!pman->GetWorkspace()->IsDefault() && !pman->LoadWorkspace())
2894 {
2895 // do not add the default workspace in recent projects list
2896 // it's always one menu click away
2897 cbMessageBox(_("Can't open default workspace (file exists?)"), _("Warning"), wxICON_WARNING);
2898 }
2899 }
2900
OnFileSaveWorkspace(cb_unused wxCommandEvent & event)2901 void MainFrame::OnFileSaveWorkspace(cb_unused wxCommandEvent& event)
2902 {
2903 ProjectManager *pman = Manager::Get()->GetProjectManager();
2904 if (pman->SaveWorkspace())
2905 m_projectsHistory.AddToHistory(pman->GetWorkspace()->GetFilename());
2906 }
2907
OnFileSaveWorkspaceAs(cb_unused wxCommandEvent & event)2908 void MainFrame::OnFileSaveWorkspaceAs(cb_unused wxCommandEvent& event)
2909 {
2910 ProjectManager *pman = Manager::Get()->GetProjectManager();
2911 if (pman->SaveWorkspaceAs(_T("")))
2912 m_projectsHistory.AddToHistory(pman->GetWorkspace()->GetFilename());
2913 }
2914
OnFileCloseWorkspace(cb_unused wxCommandEvent & event)2915 void MainFrame::OnFileCloseWorkspace(cb_unused wxCommandEvent& event)
2916 {
2917 DoCloseCurrentWorkspace();
2918 }
2919
OnFileClose(cb_unused wxCommandEvent & event)2920 void MainFrame::OnFileClose(cb_unused wxCommandEvent& event)
2921 {
2922 Manager::Get()->GetEditorManager()->CloseActive();
2923 DoUpdateStatusBar();
2924 Refresh();
2925 }
2926
OnFileCloseAll(cb_unused wxCommandEvent & event)2927 void MainFrame::OnFileCloseAll(cb_unused wxCommandEvent& event)
2928 {
2929 Manager::Get()->GetEditorManager()->CloseAll();
2930 DoUpdateStatusBar();
2931 }
2932
OnFileNext(cb_unused wxCommandEvent & event)2933 void MainFrame::OnFileNext(cb_unused wxCommandEvent& event)
2934 {
2935 Manager::Get()->GetEditorManager()->ActivateNext();
2936 DoUpdateStatusBar();
2937 }
2938
OnFilePrev(cb_unused wxCommandEvent & event)2939 void MainFrame::OnFilePrev(cb_unused wxCommandEvent& event)
2940 {
2941 Manager::Get()->GetEditorManager()->ActivatePrevious();
2942 DoUpdateStatusBar();
2943 }
2944
OnFilePrint(cb_unused wxCommandEvent & event)2945 void MainFrame::OnFilePrint(cb_unused wxCommandEvent& event)
2946 {
2947 PrintDialog dlg(this);
2948 PlaceWindow(&dlg);
2949 if (dlg.ShowModal() == wxID_OK)
2950 Manager::Get()->GetEditorManager()->Print(dlg.GetPrintScope(), dlg.GetPrintColourMode(), dlg.GetPrintLineNumbers());
2951 }
2952
OnFileQuit(cb_unused wxCommandEvent & event)2953 void MainFrame::OnFileQuit(cb_unused wxCommandEvent& event)
2954 {
2955 Close(false);
2956 }
2957
OnEraseBackground(wxEraseEvent & event)2958 void MainFrame::OnEraseBackground(wxEraseEvent& event)
2959 {
2960 // for flicker-free display
2961 event.Skip();
2962 }
2963
OnSize(wxSizeEvent & event)2964 void MainFrame::OnSize(wxSizeEvent& event)
2965 {
2966 // Highlightbutton
2967 if (m_pHighlightButton)
2968 {
2969 wxRect rect;
2970 if ( GetStatusBar()->GetFieldRect(1, rect) )
2971 {
2972 m_pHighlightButton->SetPosition(rect.GetPosition());
2973 m_pHighlightButton->SetSize(rect.GetSize());
2974 }
2975 }
2976
2977 // for flicker-free display
2978 event.Skip();
2979 }
2980
OnApplicationClose(wxCloseEvent & event)2981 void MainFrame::OnApplicationClose(wxCloseEvent& event)
2982 {
2983 if (m_InitiatedShutdown)
2984 return;
2985
2986 CodeBlocksEvent evt(cbEVT_APP_START_SHUTDOWN);
2987 Manager::Get()->ProcessEvent(evt);
2988
2989 m_InitiatedShutdown = true;
2990 Manager::BlockYields(true);
2991
2992 {
2993 // Check if any compiler plugin is building and ask the user if he/she wants to stop it.
2994 bool hasRunning = cbHasRunningCompilers(Manager::Get()->GetPluginManager());
2995 if (hasRunning)
2996 {
2997 int result = cbMessageBox(_("Currently compiling. Stop compilation and exit?"),
2998 _("Question"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION,
2999 this);
3000 if (result == wxID_YES)
3001 cbStopRunningCompilers(Manager::Get()->GetPluginManager());
3002 else
3003 {
3004 event.Veto();
3005 wxBell();
3006 m_InitiatedShutdown = false;
3007 Manager::BlockYields(false);
3008 return;
3009 }
3010 }
3011 }
3012
3013 if (!ProjectManager::CanShutdown() || !EditorManager::CanShutdown())
3014 {
3015 event.Veto();
3016 wxBell();
3017 m_InitiatedShutdown = false;
3018 Manager::BlockYields(false);
3019 return;
3020 }
3021
3022 if (!DoCloseCurrentWorkspace())
3023 {
3024 event.Veto();
3025 m_InitiatedShutdown = false;
3026 Manager::BlockYields(false);
3027 return;
3028 }
3029
3030 Manager::SetAppShuttingDown(true);
3031
3032 Manager::Get()->GetLogManager()->DebugLog(_T("Deinitializing plugins..."));
3033 CodeBlocksEvent evtShutdown(cbEVT_APP_START_SHUTDOWN);
3034 Manager::Get()->ProcessEvent(evtShutdown);
3035 Manager::Yield();
3036
3037 if (!Manager::IsBatchBuild())
3038 SaveWindowState();
3039
3040 if (m_pPrjManUI->GetNotebook())
3041 m_LayoutManager.DetachPane(m_pPrjManUI->GetNotebook());
3042 m_LayoutManager.DetachPane(m_pInfoPane);
3043 m_LayoutManager.DetachPane(Manager::Get()->GetEditorManager()->GetNotebook());
3044
3045 m_LayoutManager.UnInit();
3046 TerminateRecentFilesHistory();
3047
3048 // remove all other event handlers from this window
3049 // this stops it from crashing, when no plugins are loaded
3050 while (GetEventHandler() != this)
3051 PopEventHandler(false);
3052
3053 // Hide the window
3054 Hide();
3055
3056 if (!Manager::IsBatchBuild())
3057 {
3058 m_pInfoPane->Destroy();
3059 m_pInfoPane = nullptr;
3060 }
3061
3062 // Disconnect the mouse right click event handler for toolbars, this should be done before the plugin is
3063 // unloaded in Manager::Shutdown().
3064 PluginToolbarsMap::iterator it;
3065 for( it = m_PluginsTools.begin(); it != m_PluginsTools.end(); ++it )
3066 {
3067 wxToolBar* toolbar = it->second;
3068 if (toolbar)//Disconnect the mouse right click event handler before the toolbar is destroyed
3069 {
3070 bool result = toolbar->Disconnect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick));
3071 cbAssert(result);
3072 }
3073 }
3074
3075 Manager::Shutdown(); // Shutdown() is not Free(), Manager is automatically destroyed at exit
3076
3077 Destroy();
3078 }
3079
OnEditSwapHeaderSource(cb_unused wxCommandEvent & event)3080 void MainFrame::OnEditSwapHeaderSource(cb_unused wxCommandEvent& event)
3081 {
3082 Manager::Get()->GetEditorManager()->SwapActiveHeaderSource();
3083 DoUpdateStatusBar();
3084 }
3085
OnEditGotoMatchingBrace(cb_unused wxCommandEvent & event)3086 void MainFrame::OnEditGotoMatchingBrace(cb_unused wxCommandEvent& event)
3087 {
3088 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3089 if (ed)
3090 ed->GotoMatchingBrace();
3091 }
3092
OnEditBookmarksToggle(cb_unused wxCommandEvent & event)3093 void MainFrame::OnEditBookmarksToggle(cb_unused wxCommandEvent& event)
3094 {
3095 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3096 if (ed && ed->IsBuiltinEditor())
3097 static_cast<cbEditor*>(ed)->ToggleBookmark();
3098 }
3099
OnEditBookmarksNext(cb_unused wxCommandEvent & event)3100 void MainFrame::OnEditBookmarksNext(cb_unused wxCommandEvent& event)
3101 {
3102 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3103 if (ed && ed->IsBuiltinEditor())
3104 static_cast<cbEditor*>(ed)->GotoNextBookmark();
3105 }
3106
OnEditBookmarksPrevious(cb_unused wxCommandEvent & event)3107 void MainFrame::OnEditBookmarksPrevious(cb_unused wxCommandEvent& event)
3108 {
3109 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3110 if (ed && ed->IsBuiltinEditor())
3111 static_cast<cbEditor*>(ed)->GotoPreviousBookmark();
3112 }
3113
OnEditBookmarksClearAll(cb_unused wxCommandEvent & event)3114 void MainFrame::OnEditBookmarksClearAll(cb_unused wxCommandEvent& event)
3115 {
3116 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3117 if (ed && ed->IsBuiltinEditor())
3118 static_cast<cbEditor*>(ed)->ClearAllBookmarks();
3119 }
3120
OnEditUndo(cb_unused wxCommandEvent & event)3121 void MainFrame::OnEditUndo(cb_unused wxCommandEvent& event)
3122 {
3123 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3124 if (ed && ed->CanUndo())
3125 {
3126 cbEditor* cbEd = Manager::Get()->GetEditorManager()->GetBuiltinEditor(ed);
3127 if (cbEd && cbEd->GetControl()->AutoCompActive())
3128 cbEd->GetControl()->AutoCompCancel();
3129 ed->Undo();
3130 }
3131 }
3132
OnEditRedo(cb_unused wxCommandEvent & event)3133 void MainFrame::OnEditRedo(cb_unused wxCommandEvent& event)
3134 {
3135 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3136 if (ed)
3137 ed->Redo();
3138 }
3139
OnEditClearHistory(cb_unused wxCommandEvent & event)3140 void MainFrame::OnEditClearHistory(cb_unused wxCommandEvent& event)
3141 {
3142 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3143 if (ed)
3144 ed->ClearHistory();
3145 }
3146
OnEditCopy(cb_unused wxCommandEvent & event)3147 void MainFrame::OnEditCopy(cb_unused wxCommandEvent& event)
3148 {
3149 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3150 if (ed)
3151 ed->Copy();
3152 }
3153
OnEditCut(cb_unused wxCommandEvent & event)3154 void MainFrame::OnEditCut(cb_unused wxCommandEvent& event)
3155 {
3156 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3157 if (ed)
3158 ed->Cut();
3159 }
3160
OnEditPaste(cb_unused wxCommandEvent & event)3161 void MainFrame::OnEditPaste(cb_unused wxCommandEvent& event)
3162 {
3163 EditorBase* ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
3164 if (ed)
3165 ed->Paste();
3166 }
3167
OnEditParaUp(cb_unused wxCommandEvent & event)3168 void MainFrame::OnEditParaUp(cb_unused wxCommandEvent& event)
3169 {
3170 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3171 if (ed)
3172 ed->GetControl()->ParaUp();
3173 }
3174
OnEditParaUpExtend(cb_unused wxCommandEvent & event)3175 void MainFrame::OnEditParaUpExtend(cb_unused wxCommandEvent& event)
3176 {
3177 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3178 if (ed)
3179 ed->GetControl()->ParaUpExtend();
3180 }
3181
OnEditParaDown(cb_unused wxCommandEvent & event)3182 void MainFrame::OnEditParaDown(cb_unused wxCommandEvent& event)
3183 {
3184 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3185 if (ed)
3186 ed->GetControl()->ParaDown();
3187 }
3188
OnEditParaDownExtend(cb_unused wxCommandEvent & event)3189 void MainFrame::OnEditParaDownExtend(cb_unused wxCommandEvent& event)
3190 {
3191 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3192 if (ed)
3193 ed->GetControl()->ParaDownExtend();
3194 }
3195
OnEditWordPartLeft(cb_unused wxCommandEvent & event)3196 void MainFrame::OnEditWordPartLeft(cb_unused wxCommandEvent& event)
3197 {
3198 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3199 if (ed)
3200 ed->GetControl()->WordPartLeft();
3201 }
3202
OnEditWordPartLeftExtend(cb_unused wxCommandEvent & event)3203 void MainFrame::OnEditWordPartLeftExtend(cb_unused wxCommandEvent& event)
3204 {
3205 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3206 if (ed)
3207 ed->GetControl()->WordPartLeftExtend();
3208 }
3209
OnEditWordPartRight(cb_unused wxCommandEvent & event)3210 void MainFrame::OnEditWordPartRight(cb_unused wxCommandEvent& event)
3211 {
3212 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3213 if (ed)
3214 ed->GetControl()->WordPartRight();
3215 }
3216
OnEditWordPartRightExtend(cb_unused wxCommandEvent & event)3217 void MainFrame::OnEditWordPartRightExtend(cb_unused wxCommandEvent& event)
3218 {
3219 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3220 if (ed)
3221 ed->GetControl()->WordPartRightExtend();
3222 }
3223
OnEditZoomIn(cb_unused wxCommandEvent & event)3224 void MainFrame::OnEditZoomIn(cb_unused wxCommandEvent& event)
3225 {
3226 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3227 if (ed)
3228 ed->GetControl()->ZoomIn();
3229 }
3230
OnEditZoomOut(cb_unused wxCommandEvent & event)3231 void MainFrame::OnEditZoomOut(cb_unused wxCommandEvent& event)
3232 {
3233 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3234 if (ed)
3235 ed->GetControl()->ZoomOut();
3236 }
3237
OnEditZoomReset(cb_unused wxCommandEvent & event)3238 void MainFrame::OnEditZoomReset(cb_unused wxCommandEvent& event)
3239 {
3240 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3241 if (ed)
3242 ed->GetControl()->SetZoom(0);
3243 }
3244
OnEditLineCut(cb_unused wxCommandEvent & event)3245 void MainFrame::OnEditLineCut(cb_unused wxCommandEvent& event)
3246 {
3247 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3248 if (ed)
3249 ed->GetControl()->LineCut();
3250 }
3251
OnEditLineDelete(cb_unused wxCommandEvent & event)3252 void MainFrame::OnEditLineDelete(cb_unused wxCommandEvent& event)
3253 {
3254 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3255 if (ed)
3256 ed->GetControl()->LineDelete();
3257 }
3258
OnEditLineDuplicate(cb_unused wxCommandEvent & event)3259 void MainFrame::OnEditLineDuplicate(cb_unused wxCommandEvent& event)
3260 {
3261 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3262 if (ed)
3263 ed->GetControl()->LineDuplicate();
3264 }
3265
OnEditLineTranspose(cb_unused wxCommandEvent & event)3266 void MainFrame::OnEditLineTranspose(cb_unused wxCommandEvent& event)
3267 {
3268 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3269 if (ed)
3270 ed->GetControl()->LineTranspose();
3271 }
3272
OnEditLineCopy(cb_unused wxCommandEvent & event)3273 void MainFrame::OnEditLineCopy(cb_unused wxCommandEvent& event)
3274 {
3275 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3276 if (ed)
3277 ed->GetControl()->LineCopy();
3278 }
3279
OnEditLinePaste(cb_unused wxCommandEvent & event)3280 void MainFrame::OnEditLinePaste(cb_unused wxCommandEvent& event)
3281 {
3282 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3283 if (ed)
3284 {
3285 //We want to undo all in one step
3286 ed->GetControl()->BeginUndoAction();
3287
3288 int pos = ed->GetControl()->GetCurrentPos();
3289 int line = ed->GetControl()->LineFromPosition(pos);
3290 ed->GetControl()->GotoLine(line);
3291 int column = pos - ed->GetControl()->GetCurrentPos();
3292 ed->GetControl()->Paste();
3293 pos = ed->GetControl()->GetCurrentPos();
3294 ed->GetControl()->GotoPos(pos+column);
3295
3296 ed->GetControl()->EndUndoAction();
3297 }
3298 }
3299
OnEditLineMove(wxCommandEvent & event)3300 void MainFrame::OnEditLineMove(wxCommandEvent& event)
3301 {
3302 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3303 if (!ed)
3304 return;
3305
3306 // TODO (mortenmacfly##): Exclude rectangle selection here or not? What behaviour the majority of users expect here???
3307 cbStyledTextCtrl* stc = ed->GetControl();
3308 if (!stc || /*stc->SelectionIsRectangle() ||*/ (stc->GetSelections() > 1))
3309 return;
3310 if (stc->GetLineCount() < 3) // why are you trying to move lines anyways?
3311 return;
3312
3313 // note that these function calls are a much simpler, however
3314 // they cause text to unnecessarily be marked as modified
3315 // if (event.GetId() == idEditLineUp)
3316 // stc->MoveSelectedLinesUp();
3317 // else
3318 // stc->MoveSelectedLinesDown();
3319
3320 int startPos = stc->PositionFromLine(stc->LineFromPosition(stc->GetSelectionStart()));
3321 int endPos = stc->LineFromPosition(stc->GetSelectionEnd()); // is line
3322 if ( stc->GetSelectionEnd() == stc->PositionFromLine(endPos) // end is in first column
3323 && stc->PositionFromLine(endPos) != stc->GetLineEndPosition(endPos) // this line has text
3324 && endPos > stc->LineFromPosition(startPos) ) // start and end are on different lines
3325 {
3326 --endPos; // do not unexpectedly select another line
3327 }
3328 const bool isLastLine = (endPos == stc->GetLineCount() - 1);
3329 // warning: stc->GetLineEndPosition(endPos) yields strange results for CR LF (see bug 18892)
3330 endPos = ( isLastLine ? stc->GetLineEndPosition(endPos)
3331 : stc->PositionFromLine(endPos + 1) - 1 ); // is position
3332 if (event.GetId() == idEditLineUp)
3333 {
3334 if (stc->LineFromPosition(startPos) < 1)
3335 return; // cannot move up (we are at the top), exit
3336 stc->BeginUndoAction();
3337 const int offset = (isLastLine ? startPos - stc->GetLineEndPosition(stc->LineFromPosition(startPos) - 1) : 0);
3338 const int lineLength = startPos - stc->PositionFromLine(stc->LineFromPosition(startPos) - 1);
3339 const wxString line = stc->GetTextRange(startPos - lineLength - offset,
3340 startPos - offset);
3341 stc->InsertText(endPos + (isLastLine ? 0 : 1), line);
3342 // warning: line.Length() != lineLength if multibyte characters are used
3343 stc->DeleteRange(startPos - lineLength, lineLength);
3344 startPos -= lineLength;
3345 endPos -= lineLength;
3346 stc->EndUndoAction();
3347 }
3348 else // event.GetId() == idEditLineDown
3349 {
3350 if (isLastLine)
3351 return; // cannot move down (we are at the bottom), exit
3352 stc->BeginUndoAction();
3353 const int lineLength = stc->PositionFromLine(stc->LineFromPosition(endPos + 1) + 1) - endPos - 1;
3354 const wxString line = stc->GetTextRange(endPos + 1,
3355 endPos + 1 + lineLength);
3356 stc->InsertText(startPos, line);
3357 // warning: line.Length() != lineLength if multibyte characters are used
3358 startPos += lineLength;
3359 endPos += lineLength;
3360 stc->DeleteRange(endPos + 1, lineLength);
3361 stc->EndUndoAction();
3362 }
3363 stc->SetSelectionVoid(startPos, endPos);
3364 }
3365
OnEditUpperCase(cb_unused wxCommandEvent & event)3366 void MainFrame::OnEditUpperCase(cb_unused wxCommandEvent& event)
3367 {
3368 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3369 if (ed)
3370 ed->GetControl()->UpperCase();
3371 }
3372
OnEditLowerCase(cb_unused wxCommandEvent & event)3373 void MainFrame::OnEditLowerCase(cb_unused wxCommandEvent& event)
3374 {
3375 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3376 if (ed)
3377 ed->GetControl()->LowerCase();
3378 }
3379
OnEditInsertNewLine(wxCommandEvent & event)3380 void MainFrame::OnEditInsertNewLine(wxCommandEvent& event)
3381 {
3382 OnEditGotoLineEnd(event);
3383 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3384 if (ed)
3385 {
3386 cbStyledTextCtrl* stc = ed->GetControl();
3387 if (stc->AutoCompActive())
3388 stc->AutoCompCancel();
3389 stc->NewLine();
3390 }
3391 }
3392
OnEditGotoLineEnd(cb_unused wxCommandEvent & event)3393 void MainFrame::OnEditGotoLineEnd(cb_unused wxCommandEvent& event)
3394 {
3395 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3396 if (ed)
3397 {
3398 cbStyledTextCtrl* stc = ed->GetControl();
3399 if (stc->AutoCompActive())
3400 stc->AutoCompCancel();
3401 stc->LineEnd();
3402 }
3403 }
3404
InsertNewLine(bool below)3405 static void InsertNewLine(bool below)
3406 {
3407 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3408 if (ed)
3409 {
3410 cbStyledTextCtrl* stc = ed->GetControl();
3411 stc->BeginUndoAction();
3412 if (stc->AutoCompActive())
3413 stc->AutoCompCancel();
3414
3415 if (below)
3416 {
3417 stc->LineEndDisplay();
3418 int pos = stc->GetCurrentPos();
3419 stc->InsertText(pos, GetEOLStr(stc->GetEOLMode()));
3420 stc->LineDown();
3421 }
3422 else
3423 {
3424 stc->HomeDisplay();
3425 int pos = stc->GetCurrentPos();
3426 stc->InsertText(pos, GetEOLStr(stc->GetEOLMode()));
3427 stc->EndUndoAction();
3428 }
3429 stc->EndUndoAction();
3430 }
3431 }
3432
OnEditInsertNewLineBelow(cb_unused wxCommandEvent & event)3433 void MainFrame::OnEditInsertNewLineBelow(cb_unused wxCommandEvent& event)
3434 {
3435 InsertNewLine(true);
3436 }
3437
OnEditInsertNewLineAbove(cb_unused wxCommandEvent & event)3438 void MainFrame::OnEditInsertNewLineAbove(cb_unused wxCommandEvent& event)
3439 {
3440 InsertNewLine(false);
3441 }
3442
OnEditSelectAll(cb_unused wxCommandEvent & event)3443 void MainFrame::OnEditSelectAll(cb_unused wxCommandEvent& event)
3444 {
3445 EditorBase* eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
3446 if (eb)
3447 eb->SelectAll();
3448 }
3449
3450 namespace
3451 {
3452
3453 struct EditorSelection
3454 {
3455 long caret, anchor;
3456
Empty__anon5b41abdd0311::EditorSelection3457 bool Empty() const { return caret == anchor; }
IsReversed__anon5b41abdd0311::EditorSelection3458 bool IsReversed() const { return caret < anchor; }
3459
GetStart__anon5b41abdd0311::EditorSelection3460 long GetStart() const { return std::min(caret, anchor); }
GetEnd__anon5b41abdd0311::EditorSelection3461 long GetEnd() const { return std::max(caret, anchor); }
3462
Contains__anon5b41abdd0311::EditorSelection3463 bool Contains(const EditorSelection &selection) const
3464 {
3465 return !(GetEnd() < selection.GetStart() || GetStart() > selection.GetEnd());
3466 }
3467 };
3468
SelectNext(cbStyledTextCtrl * control,const wxString & selectedText,long selectionEnd,bool reversed)3469 bool SelectNext(cbStyledTextCtrl *control, const wxString &selectedText, long selectionEnd, bool reversed)
3470 {
3471 // always match case and try to match whole words if they have no special characters
3472 int flag = wxSCI_FIND_MATCHCASE;
3473 if (selectedText.find_first_of(wxT(";:\"'`~@#$%^,-+*/\\=|!?&*(){}[]")) == wxString::npos)
3474 flag |= wxSCI_FIND_WHOLEWORD;
3475
3476 int endPos = 0; // we need this to work properly with multibyte characters
3477 int eof = control->GetLength();
3478 int pos = control->FindText(selectionEnd, eof, selectedText, flag, &endPos);
3479 if (pos != wxSCI_INVALID_POSITION)
3480 {
3481 control->SetAdditionalSelectionTyping(true);
3482 control->SetMultiPaste(true);
3483 control->IndicatorClearRange(pos, endPos - pos);
3484 if (reversed)
3485 control->AddSelection(pos, endPos);
3486 else
3487 control->AddSelection(endPos, pos);
3488 control->MakeNearbyLinesVisible(control->LineFromPosition(pos));
3489 return true;
3490 }
3491 else
3492 {
3493 InfoWindow::Display(_("Select Next Occurrence"), _("No more available"));
3494 return false;
3495 }
3496 }
3497
GetSelectionInEditor(EditorSelection & selection,cbStyledTextCtrl * control)3498 bool GetSelectionInEditor(EditorSelection &selection, cbStyledTextCtrl *control)
3499 {
3500 int main = control->GetMainSelection();
3501 int count = control->GetSelections();
3502 if (main >=0 && main < count)
3503 {
3504 selection.caret = control->GetSelectionNCaret(main);
3505 selection.anchor = control->GetSelectionNAnchor(main);
3506 return true;
3507 }
3508 else
3509 return false;
3510 }
3511
3512 } // anonymous namespace
3513
OnEditSelectNext(cb_unused wxCommandEvent & event)3514 void MainFrame::OnEditSelectNext(cb_unused wxCommandEvent& event)
3515 {
3516 EditorBase* eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
3517 if (!eb || !eb->IsBuiltinEditor())
3518 return;
3519 cbStyledTextCtrl *control = static_cast<cbEditor*>(eb)->GetControl();
3520
3521 EditorSelection selection;
3522 if (!GetSelectionInEditor(selection, control))
3523 return;
3524
3525 if (!selection.Empty())
3526 {
3527 const wxString &selectedText(control->GetTextRange(selection.GetStart(), selection.GetEnd()));
3528 SelectNext(control, selectedText, selection.GetEnd(), selection.IsReversed());
3529 }
3530 else
3531 {
3532 // Select word at the cursor position if there is nothing selected.
3533 const int start = control->WordStartPosition(selection.caret, true);
3534 const int end = control->WordEndPosition(selection.caret, true);
3535 control->SetSelection(start, end);
3536 }
3537 }
3538
OnEditSelectNextSkip(cb_unused wxCommandEvent & event)3539 void MainFrame::OnEditSelectNextSkip(cb_unused wxCommandEvent& event)
3540 {
3541 EditorBase* eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
3542 if (!eb || !eb->IsBuiltinEditor())
3543 return;
3544 cbStyledTextCtrl *control = static_cast<cbEditor*>(eb)->GetControl();
3545
3546 EditorSelection selection;
3547 if (!GetSelectionInEditor(selection, control))
3548 return;
3549
3550 ConfigManager *cfgEditor = Manager::Get()->GetConfigManager(wxT("editor"));
3551 bool highlightOccurrences = cfgEditor->ReadBool(wxT("/highlight_occurrence/enabled"), true);
3552
3553 // Select the next occurrence first. This prevents a cursor created at the beginning of the
3554 // file when the user uses the command when there is a single selection. Scintilla always makes
3555 // sure that there is at least one selection/cursor. So if we clear all selections it creates a
3556 // cursor at the beginning of the file.
3557 const wxString &selectedText(control->GetTextRange(selection.GetStart(), selection.GetEnd()));
3558 if (!SelectNext(control, selectedText, selection.GetEnd(), selection.IsReversed()))
3559 return; // If there is no new selection don't deselect the current one.
3560
3561 // store the selections in a vector except for the current one
3562 typedef std::vector<EditorSelection> Selections;
3563 Selections selections;
3564 int count = control->GetSelections();
3565 for (int ii = 0; ii < count; ++ii)
3566 {
3567 EditorSelection item;
3568 item.caret = control->GetSelectionNCaret(ii);
3569 item.anchor = control->GetSelectionNAnchor(ii);
3570
3571 if (!item.Contains(selection))
3572 selections.push_back(item);
3573 else if (highlightOccurrences)
3574 {
3575 // Restore the indicator for the highlight occurrences if they are enabled.
3576 control->IndicatorFillRange(item.GetStart(), item.GetEnd());
3577 }
3578 }
3579
3580 control->ClearSelections();
3581 Selections::const_iterator it = selections.begin();
3582 int index = 0;
3583 if (it != selections.end() && control->GetSelections() > 0)
3584 {
3585 control->SetSelectionNAnchor(index, it->anchor);
3586 control->SetSelectionNCaret(index, it->caret);
3587 ++index;
3588 ++it;
3589 }
3590 for (; it != selections.end(); ++it)
3591 {
3592 control->AddSelection(it->caret, it->anchor);
3593 ++index;
3594 }
3595 }
3596
3597 /* This is a shameless rip-off of the original OnEditCommentSelected function,
3598 * now more suitingly named OnEditToggleCommentSelected (because that's what
3599 * it does :)
3600 */
OnEditCommentSelected(cb_unused wxCommandEvent & event)3601 void MainFrame::OnEditCommentSelected(cb_unused wxCommandEvent& event)
3602 {
3603 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3604 if (!ed)
3605 return;
3606
3607 cbStyledTextCtrl* stc = ed->GetControl();
3608 if (!stc)
3609 return;
3610
3611 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3612 if (!colour_set)
3613 return;
3614
3615 CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3616 if (comment.lineComment==wxEmptyString && comment.streamCommentStart==wxEmptyString)
3617 return;
3618
3619 stc->BeginUndoAction();
3620 if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3621 {
3622 int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3623 int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3624 int curLine=startLine;
3625 /**
3626 Fix a glitch: when selecting multiple lines and the caret
3627 is at the start of the line after the last line selected,
3628 the code would, wrongly, (un)comment that line too.
3629 This fixes it.
3630 */
3631 if (startLine != endLine && // selection is more than one line
3632 stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3633 {
3634 // don't take into account the line the caret is on,
3635 // because it contains no selection (caret_column == 0)...
3636 --endLine;
3637 }
3638
3639 while( curLine <= endLine )
3640 {
3641 // For each line: comment.
3642 if (comment.lineComment!=wxEmptyString)
3643 stc->InsertText( stc->PositionFromLine( curLine ), comment.lineComment );
3644 else // if the language doesn't support line comments use stream comments
3645 {
3646 stc->InsertText( stc->PositionFromLine( curLine ), comment.streamCommentStart );
3647 stc->InsertText( stc->GetLineEndPosition( curLine ), comment.streamCommentEnd );
3648 }
3649 ++curLine;
3650 } // end while
3651 stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3652 }
3653 stc->EndUndoAction();
3654 }
3655
3656 /* See above (OnEditCommentSelected) for details. */
OnEditUncommentSelected(cb_unused wxCommandEvent & event)3657 void MainFrame::OnEditUncommentSelected(cb_unused wxCommandEvent& event)
3658 {
3659 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3660 if (!ed)
3661 return;
3662
3663 cbStyledTextCtrl* stc = ed->GetControl();
3664 if (!stc)
3665 return;
3666
3667 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3668 if (!colour_set)
3669 return;
3670
3671 CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3672 if (comment.lineComment==wxEmptyString && comment.streamCommentStart==wxEmptyString)
3673 return;
3674
3675 stc->BeginUndoAction();
3676 if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3677 {
3678 int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3679 int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3680 int curLine = startLine;
3681 /**
3682 Fix a glitch: when selecting multiple lines and the caret
3683 is at the start of the line after the last line selected,
3684 the code would, wrongly, (un)comment that line too.
3685 This fixes it.
3686 */
3687 if (startLine != endLine && // selection is more than one line
3688 stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3689 {
3690 // don't take into account the line the caret is on,
3691 // because it contains no selection (caret_column == 0)...
3692 --endLine;
3693 }
3694
3695 while( curLine <= endLine )
3696 {
3697 // For each line: if it is commented, uncomment.
3698 wxString strLine = stc->GetLine( curLine );
3699
3700 bool startsWithComment;
3701 bool endsWithComment;
3702
3703 // check for line comment
3704 startsWithComment = strLine.Strip( wxString::leading ).StartsWith( comment.lineComment );
3705 if ( startsWithComment )
3706 { // we know the comment is there (maybe preceded by white space)
3707 int Pos = strLine.Find(comment.lineComment);
3708 int start = stc->PositionFromLine( curLine ) + Pos;
3709 int end = start + comment.lineComment.Length();
3710 stc->SetTargetStart( start );
3711 stc->SetTargetEnd( end );
3712 stc->ReplaceTarget( wxEmptyString );
3713 }
3714
3715 // check for stream comment
3716 startsWithComment = strLine.Strip( wxString::leading ).StartsWith( comment.streamCommentStart ); // check for stream comment start
3717 endsWithComment = strLine.Strip( wxString::trailing ).EndsWith( comment.streamCommentEnd); // check for stream comment end
3718 if ( startsWithComment && endsWithComment )
3719 {
3720 int Pos;
3721 int start;
3722 int end;
3723
3724 // we know the start comment is there (maybe preceded by white space)
3725 Pos = strLine.Find(comment.streamCommentStart);
3726 start = stc->PositionFromLine( curLine ) + Pos;
3727 end = start + comment.streamCommentStart.Length();
3728 stc->SetTargetStart( start );
3729 stc->SetTargetEnd( end );
3730 stc->ReplaceTarget( wxEmptyString );
3731
3732 // we know the end comment is there too (maybe followed by white space)
3733 // attention!! we have to subtract the length of the comment we already removed
3734 Pos = strLine.rfind(comment.streamCommentEnd,strLine.npos) - comment.streamCommentStart.Length();
3735 start = stc->PositionFromLine( curLine ) + Pos;
3736 end = start + comment.streamCommentEnd.Length();
3737 stc->SetTargetStart( start );
3738 stc->SetTargetEnd( end );
3739 stc->ReplaceTarget( wxEmptyString );
3740 }
3741 ++curLine;
3742 } // end while
3743 stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3744 }
3745 stc->EndUndoAction();
3746 }
3747
OnEditToggleCommentSelected(cb_unused wxCommandEvent & event)3748 void MainFrame::OnEditToggleCommentSelected(cb_unused wxCommandEvent& event)
3749 {
3750 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3751 if (!ed)
3752 return;
3753
3754 cbStyledTextCtrl* stc = ed->GetControl();
3755 if (!stc)
3756 return;
3757
3758 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3759 if (!colour_set)
3760 return;
3761
3762 wxString comment = colour_set->GetCommentToken( ed->GetLanguage() ).lineComment;
3763 if (comment==wxEmptyString)
3764 return;
3765
3766 stc->BeginUndoAction();
3767 if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3768 {
3769 int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3770 int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3771 int curLine = startLine;
3772 /**
3773 Fix a glitch: when selecting multiple lines and the caret
3774 is at the start of the line after the last line selected,
3775 the code would, wrongly, (un)comment that line too.
3776 This fixes it.
3777 */
3778 if (startLine != endLine && // selection is more than one line
3779 stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3780 {
3781 // don't take into account the line the caret is on,
3782 // because it contains no selection (caret_column == 0)...
3783 --endLine;
3784 }
3785
3786 bool doComment = false;
3787 while( curLine <= endLine )
3788 {
3789 // Check is any of the selected lines is commented
3790 wxString strLine = stc->GetLine( curLine );
3791 int commentPos = strLine.Strip( wxString::leading ).Find( comment );
3792
3793 if (commentPos != 0)
3794 {
3795 // At least one line is not commented, so comment the whole selection
3796 // (else if all lines are commented, uncomment the selection)
3797 doComment = true;
3798 break;
3799 }
3800 ++curLine;
3801 }
3802
3803 curLine = startLine;
3804 while( curLine <= endLine )
3805 {
3806 if (doComment)
3807 stc->InsertText( stc->PositionFromLine( curLine ), comment );
3808 else
3809 {
3810 // we know the comment is there (maybe preceded by white space)
3811 wxString strLine = stc->GetLine( curLine );
3812 int Pos = strLine.Find(comment);
3813 int start = stc->PositionFromLine( curLine ) + Pos;
3814 int end = start + comment.Length();
3815 stc->SetTargetStart( start );
3816 stc->SetTargetEnd( end );
3817 stc->ReplaceTarget( wxEmptyString );
3818 }
3819 ++curLine;
3820 }
3821 stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3822 }
3823 stc->EndUndoAction();
3824 }
3825
OnEditStreamCommentSelected(cb_unused wxCommandEvent & event)3826 void MainFrame::OnEditStreamCommentSelected(cb_unused wxCommandEvent& event)
3827 {
3828 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3829 if (!ed)
3830 return;
3831
3832 cbStyledTextCtrl* stc = ed->GetControl();
3833 if (!stc)
3834 return;
3835
3836 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3837 if (!colour_set)
3838 return;
3839
3840 CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3841 if (comment.streamCommentStart==wxEmptyString)
3842 return;
3843
3844 stc->BeginUndoAction();
3845 if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3846 {
3847 int startPos = stc->GetSelectionStart();
3848 int endPos = stc->GetSelectionEnd();
3849 if ( startPos == endPos )
3850 { // if nothing selected stream comment current *word* first
3851 startPos = stc->WordStartPosition(stc->GetCurrentPos(), true);
3852 endPos = stc->WordEndPosition (stc->GetCurrentPos(), true);
3853 if ( startPos == endPos )
3854 { // if nothing selected stream comment current *line*
3855 startPos = stc->PositionFromLine (stc->LineFromPosition(startPos));
3856 endPos = stc->GetLineEndPosition(stc->LineFromPosition(startPos));
3857 }
3858 }
3859 else
3860 {
3861 /**
3862 Fix a glitch: when selecting multiple lines and the caret
3863 is at the start of the line after the last line selected,
3864 the code would, wrongly, (un)comment that line too.
3865 This fixes it.
3866 */
3867 if (stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3868 {
3869 // don't take into account the line the caret is on,
3870 // because it contains no selection (caret_column == 0)...
3871 --endPos;
3872 }
3873 }
3874 // stream comment block
3875 int p1 = startPos - 1;
3876 while (stc->GetCharAt(p1) == _T(' ') && p1 > 0)
3877 --p1;
3878 p1 -= 1;
3879 int p2 = endPos;
3880 while (stc->GetCharAt(p2) == _T(' ') && p2 < stc->GetLength())
3881 ++p2;
3882 const wxString start = stc->GetTextRange(p1, p1 + comment.streamCommentStart.Length());
3883 const wxString end = stc->GetTextRange(p2, p2 + comment.streamCommentEnd.Length());
3884 if (start == comment.streamCommentStart && end == comment.streamCommentEnd)
3885 {
3886 stc->SetTargetStart(p1);
3887 stc->SetTargetEnd(p2 + 2);
3888 wxString target = stc->GetTextRange(p1 + 2, p2);
3889 stc->ReplaceTarget(target);
3890 stc->GotoPos(p1 + target.Length());
3891 }
3892 else
3893 {
3894 stc->InsertText( startPos, comment.streamCommentStart );
3895 // we already inserted some characters so out endPos changed
3896 startPos += comment.streamCommentStart.Length();
3897 endPos += comment.streamCommentStart.Length();
3898 stc->InsertText( endPos, comment.streamCommentEnd );
3899 stc->SetSelectionVoid(startPos,endPos);
3900 }
3901
3902 }
3903 stc->EndUndoAction();
3904 }
3905
OnEditBoxCommentSelected(cb_unused wxCommandEvent & event)3906 void MainFrame::OnEditBoxCommentSelected(cb_unused wxCommandEvent& event)
3907 {
3908 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3909 if (!ed)
3910 return;
3911
3912 cbStyledTextCtrl* stc = ed->GetControl();
3913 if (!stc)
3914 return;
3915
3916 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3917 if (!colour_set)
3918 return;
3919
3920 CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3921 if (comment.boxCommentStart==wxEmptyString)
3922 return;
3923
3924 stc->BeginUndoAction();
3925 if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3926 {
3927 int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3928 int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3929 int curLine = startLine;
3930 /**
3931 Fix a glitch: when selecting multiple lines and the caret
3932 is at the start of the line after the last line selected,
3933 the code would, wrongly, (un)comment that line too.
3934 This fixes it.
3935 */
3936 if (startLine != endLine && // selection is more than one line
3937 stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3938 {
3939 // don't take into account the line the caret is on,
3940 // because it contains no selection (caret_column == 0)...
3941 --endLine;
3942 }
3943
3944
3945
3946 if (startLine == endLine) // if selection is only one line ...
3947 {
3948 // ... then insert streamcomment tokens at the beginning and the end of the line
3949 stc->InsertText( stc->PositionFromLine ( curLine ), comment.streamCommentStart );
3950 stc->InsertText( stc->GetLineEndPosition( curLine ), comment.streamCommentEnd );
3951 }
3952 else // selection is more than one line
3953 {
3954 // insert boxcomment start token
3955 stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentStart );
3956 ++curLine; // we already commented the first line about 9 lines above
3957 while( curLine <= endLine )
3958 {
3959 // For each line: comment.
3960 stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentMid );
3961 ++curLine;
3962 } // end while
3963
3964 // insert boxcomment end token and add a new line character
3965 stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentEnd + GetEOLStr(stc->GetEOLMode()) );
3966 } // end if
3967 stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3968 }
3969 stc->EndUndoAction();
3970 }
3971
OnEditShowCallTip(cb_unused wxCommandEvent & event)3972 void MainFrame::OnEditShowCallTip(cb_unused wxCommandEvent& event)
3973 {
3974 CodeBlocksEvent evt(cbEVT_SHOW_CALL_TIP);
3975 Manager::Get()->ProcessEvent(evt);
3976 }
3977
OnEditCompleteCode(cb_unused wxCommandEvent & event)3978 void MainFrame::OnEditCompleteCode(cb_unused wxCommandEvent& event)
3979 {
3980 CodeBlocksEvent evt(cbEVT_COMPLETE_CODE);
3981 Manager::Get()->ProcessEvent(evt);
3982 }
3983
OnEditHighlightMode(wxCommandEvent & event)3984 void MainFrame::OnEditHighlightMode(wxCommandEvent& event)
3985 {
3986 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3987 if (!ed)
3988 return;
3989
3990 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
3991 if (!colour_set)
3992 return;
3993
3994 HighlightLanguage lang = colour_set->GetHighlightLanguage(_T(""));
3995 if (event.GetId() != idEditHighlightModeText)
3996 {
3997 wxMenu* hl = nullptr;
3998 GetMenuBar()->FindItem(idEditHighlightModeText, &hl);
3999 if (hl)
4000 {
4001 wxMenuItem* item = hl->FindItem(event.GetId());
4002 if (item)
4003 lang = colour_set->GetHighlightLanguage(item->GetItemLabelText());
4004 }
4005 }
4006 // Highlightbutton
4007 if (m_pHighlightButton)
4008 changeButtonLabel(*m_pHighlightButton, colour_set->GetLanguageName(lang));
4009 ed->SetLanguage(lang, true);
4010 Manager::Get()->GetCCManager()->NotifyPluginStatus();
4011 }
4012
OnEditFoldAll(cb_unused wxCommandEvent & event)4013 void MainFrame::OnEditFoldAll(cb_unused wxCommandEvent& event)
4014 {
4015 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4016 if (ed)
4017 ed->FoldAll();
4018 }
4019
OnEditUnfoldAll(cb_unused wxCommandEvent & event)4020 void MainFrame::OnEditUnfoldAll(cb_unused wxCommandEvent& event)
4021 {
4022 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4023 if (ed)
4024 ed->UnfoldAll();
4025 }
4026
OnEditToggleAllFolds(cb_unused wxCommandEvent & event)4027 void MainFrame::OnEditToggleAllFolds(cb_unused wxCommandEvent& event)
4028 {
4029 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4030 if (ed)
4031 ed->ToggleAllFolds();
4032 }
4033
OnEditFoldBlock(cb_unused wxCommandEvent & event)4034 void MainFrame::OnEditFoldBlock(cb_unused wxCommandEvent& event)
4035 {
4036 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4037 if (ed)
4038 ed->FoldBlockFromLine();
4039 }
4040
OnEditUnfoldBlock(cb_unused wxCommandEvent & event)4041 void MainFrame::OnEditUnfoldBlock(cb_unused wxCommandEvent& event)
4042 {
4043 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4044 if (ed)
4045 ed->UnfoldBlockFromLine();
4046 }
4047
OnEditToggleFoldBlock(cb_unused wxCommandEvent & event)4048 void MainFrame::OnEditToggleFoldBlock(cb_unused wxCommandEvent& event)
4049 {
4050 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4051 if (ed)
4052 ed->ToggleFoldBlockFromLine();
4053 }
4054
OnEditEOLMode(wxCommandEvent & event)4055 void MainFrame::OnEditEOLMode(wxCommandEvent& event)
4056 {
4057 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4058 if (ed)
4059 {
4060 int mode = -1;
4061
4062 if (event.GetId() == idEditEOLCRLF)
4063 mode = wxSCI_EOL_CRLF;
4064 else if (event.GetId() == idEditEOLCR)
4065 mode = wxSCI_EOL_CR;
4066 else if (event.GetId() == idEditEOLLF)
4067 mode = wxSCI_EOL_LF;
4068
4069 if (mode != -1 && mode != ed->GetControl()->GetEOLMode())
4070 {
4071 ed->GetControl()->BeginUndoAction();
4072 ed->GetControl()->ConvertEOLs(mode);
4073 ed->GetControl()->SetEOLMode(mode);
4074 ed->GetControl()->EndUndoAction();
4075 }
4076 }
4077 }
4078
OnEditEncoding(wxCommandEvent & event)4079 void MainFrame::OnEditEncoding(wxCommandEvent& event)
4080 {
4081 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4082 if (!ed)
4083 return;
4084
4085 if ( event.GetId() == idEditEncodingUseBom )
4086 {
4087 ed->SetUseBom( !ed->GetUseBom() );
4088 return;
4089 }
4090
4091 wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
4092
4093 if ( event.GetId() == idEditEncodingDefault )
4094 encoding = wxFONTENCODING_SYSTEM;
4095 else if ( event.GetId() == idEditEncodingAscii )
4096 encoding = wxFONTENCODING_ISO8859_1;
4097 else if ( event.GetId() == idEditEncodingUtf7 )
4098 encoding = wxFONTENCODING_UTF7;
4099 else if ( event.GetId() == idEditEncodingUtf8 )
4100 encoding = wxFONTENCODING_UTF8;
4101 else if ( event.GetId() == idEditEncodingUtf16 )
4102 encoding = wxFONTENCODING_UTF16;
4103 else if ( event.GetId() == idEditEncodingUtf32 )
4104 encoding = wxFONTENCODING_UTF32;
4105 else if ( event.GetId() == idEditEncodingUnicode )
4106 encoding = wxFONTENCODING_UNICODE;
4107 else if ( event.GetId() == idEditEncodingUnicode16BE )
4108 encoding = wxFONTENCODING_UTF16BE;
4109 else if ( event.GetId() == idEditEncodingUnicode16LE )
4110 encoding = wxFONTENCODING_UTF16LE;
4111 else if ( event.GetId() == idEditEncodingUnicode32BE )
4112 encoding = wxFONTENCODING_UTF32BE;
4113 else if ( event.GetId() == idEditEncodingUnicode32LE )
4114 encoding = wxFONTENCODING_UTF32LE;
4115
4116 ed->SetEncoding(encoding);
4117 }
4118
OnViewLayout(wxCommandEvent & event)4119 void MainFrame::OnViewLayout(wxCommandEvent& event)
4120 {
4121 LoadViewLayout(m_PluginIDsMap[event.GetId()]);
4122 }
4123
OnViewLayoutSave(cb_unused wxCommandEvent & event)4124 void MainFrame::OnViewLayoutSave(cb_unused wxCommandEvent& event)
4125 {
4126 wxString def = m_LastLayoutName;
4127 if ( def.empty() )
4128 def = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/default"));
4129 wxString name = cbGetTextFromUser(_("Enter the name for this perspective"), _("Save current perspective"), def);
4130 if (!name.IsEmpty())
4131 {
4132 DoFixToolbarsLayout();
4133 SaveViewLayout(name,
4134 m_LayoutManager.SavePerspective(),
4135 m_pInfoPane->SaveTabOrder(),
4136 true);
4137 }
4138 }
4139
OnViewLayoutDelete(cb_unused wxCommandEvent & event)4140 void MainFrame::OnViewLayoutDelete(cb_unused wxCommandEvent& event)
4141 {
4142 if (m_LastLayoutName == gDefaultLayout)
4143 {
4144 if (cbMessageBox(_("The default perspective cannot be deleted. It can always be reverted to "
4145 "a predefined state though.\nDo you want to revert it now?"),
4146 _("Confirmation"),
4147 wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT) == wxID_YES)
4148 {
4149 m_LayoutViews[gDefaultLayout] = gDefaultLayoutData;
4150 m_LayoutMessagePane[gDefaultLayout] = gDefaultMessagePaneLayoutData;
4151 LoadViewLayout(gDefaultLayout);
4152 }
4153 return;
4154 }
4155
4156 if (m_LastLayoutName == gMinimalLayout)
4157 {
4158 if (cbMessageBox(_("The minimal layout cannot be deleted. It can always be reverted to "
4159 "a predefined state though.\nDo you want to revert it now?"),
4160 _("Confirmation"),
4161 wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT) == wxID_YES)
4162 {
4163 wxString tempLayout = m_PreviousLayoutName;
4164 m_LayoutViews[gMinimalLayout] = gMinimalLayoutData;
4165 m_LayoutMessagePane[gMinimalLayout] = gMinimalMessagePaneLayoutData;
4166 LoadViewLayout(gMinimalLayout);
4167 m_PreviousLayoutName = tempLayout;
4168 }
4169 return;
4170 }
4171
4172 if (cbMessageBox(wxString::Format(_("Are you really sure you want to delete the perspective '%s'?"), m_LastLayoutName.wx_str()),
4173 _("Confirmation"),
4174 wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT) == wxID_YES)
4175 {
4176 // first delete it from the hashmap
4177 LayoutViewsMap::iterator it = m_LayoutViews.find(m_LastLayoutName);
4178 if (it != m_LayoutViews.end())
4179 m_LayoutViews.erase(it);
4180 it = m_LayoutMessagePane.find(m_LastLayoutName);
4181 if (it != m_LayoutMessagePane.end())
4182 m_LayoutMessagePane.erase(it);
4183
4184 // now delete the menu item too
4185 wxMenu* viewLayouts = nullptr;
4186 GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
4187 if (viewLayouts)
4188 {
4189 int id = viewLayouts->FindItem(m_LastLayoutName);
4190 if (id != wxNOT_FOUND)
4191 viewLayouts->Delete(id);
4192 // delete the id from the map too
4193 PluginIDsMap::iterator it2 = m_PluginIDsMap.find(id);
4194 if (it2 != m_PluginIDsMap.end())
4195 m_PluginIDsMap.erase(it2);
4196 }
4197
4198 cbMessageBox(wxString::Format(_("Perspective '%s' deleted.\nWill now revert to perspective '%s'..."), m_LastLayoutName.wx_str(), gDefaultLayout.wx_str()),
4199 _("Information"), wxICON_INFORMATION);
4200
4201 // finally, revert to the default layout
4202 m_LastLayoutName = gDefaultLayout; // do not ask to save old layout ;)
4203 LoadViewLayout(gDefaultLayout);
4204 }
4205 }
4206
OnNotebookDoubleClick(cb_unused CodeBlocksEvent & event)4207 void MainFrame::OnNotebookDoubleClick(cb_unused CodeBlocksEvent& event)
4208 {
4209 if (m_LastLayoutName == gMinimalLayout)
4210 LoadViewLayout(m_PreviousLayoutName.IsEmpty()?Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/environment/view/layout_to_toggle"),gDefaultLayout):m_PreviousLayoutName);
4211 else
4212 {
4213 ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
4214 if (cfg->ReadBool(_T("/environment/view/dbl_clk_maximize"), true))
4215 LoadViewLayout(gMinimalLayout);
4216 }
4217 }
4218
OnViewScriptConsole(cb_unused wxCommandEvent & event)4219 void MainFrame::OnViewScriptConsole(cb_unused wxCommandEvent& event)
4220 {
4221 ShowHideScriptConsole();
4222 }
4223
OnViewHideEditorTabs(cb_unused wxCommandEvent & event)4224 void MainFrame::OnViewHideEditorTabs(cb_unused wxCommandEvent& event)
4225 {
4226 cbAuiNotebook* nb = Manager::Get()->GetEditorManager()->GetNotebook();
4227 if (nb)
4228 {
4229 bool hide_editor_tabs = nb->GetTabCtrlHeight() > 0;
4230
4231 if (hide_editor_tabs)
4232 nb->SetTabCtrlHeight(0);
4233 else
4234 nb->SetTabCtrlHeight(-1);
4235
4236 Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/environment/hide_editor_tabs"), hide_editor_tabs);
4237 }
4238 }
4239
OnSearchFind(wxCommandEvent & event)4240 void MainFrame::OnSearchFind(wxCommandEvent& event)
4241 {
4242 bool bDoMultipleFiles = (event.GetId() == idSearchFindInFiles);
4243 if (!bDoMultipleFiles)
4244 bDoMultipleFiles = !Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4245 m_findReplace.ShowFindDialog(false, bDoMultipleFiles);
4246 }
4247
OnSearchFindNext(wxCommandEvent & event)4248 void MainFrame::OnSearchFindNext(wxCommandEvent& event)
4249 {
4250 bool bNext = !(event.GetId() == idSearchFindPrevious);
4251 m_findReplace.FindNext(bNext, nullptr, nullptr, false);
4252 }
4253
OnSearchFindNextSelected(wxCommandEvent & event)4254 void MainFrame::OnSearchFindNextSelected(wxCommandEvent& event)
4255 {
4256 bool bNext = !(event.GetId() == idSearchFindSelectedPrevious);
4257 m_findReplace.FindSelectedText(bNext);
4258 }
4259
OnSearchReplace(wxCommandEvent & event)4260 void MainFrame::OnSearchReplace(wxCommandEvent& event)
4261 {
4262 bool bDoMultipleFiles = (event.GetId() == idSearchReplaceInFiles);
4263 if (!bDoMultipleFiles)
4264 bDoMultipleFiles = !Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4265 m_findReplace.ShowFindDialog(true, bDoMultipleFiles);
4266 }
4267
OnSearchGotoLine(cb_unused wxCommandEvent & event)4268 void MainFrame::OnSearchGotoLine(cb_unused wxCommandEvent& event)
4269 {
4270 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4271 if (!ed)
4272 return;
4273
4274 int max = ed->GetControl()->LineFromPosition(ed->GetControl()->GetLength()) + 1;
4275
4276 /**
4277 @remarks We use wxGetText instead of wxGetNumber because wxGetNumber *must*
4278 provide an initial line number...which doesn't make sense, and just keeps the
4279 user deleting the initial line number everytime he instantiates the dialog.
4280 However, this is just a temporary hack, because the default dialog used isn't
4281 that suitable either.
4282 */
4283 wxString strLine = cbGetTextFromUser( wxString::Format(_("Line (1 - %d): "), max),
4284 _("Goto line"),
4285 _T( "" ),
4286 this );
4287 long int line = 0;
4288 strLine.ToLong(&line);
4289 if ( line >= 1 && line <= max )
4290 {
4291 ed->UnfoldBlockFromLine(line - 1);
4292 ed->GotoLine(line - 1);
4293 }
4294 }
4295
OnSearchGotoNextChanged(cb_unused wxCommandEvent & event)4296 void MainFrame::OnSearchGotoNextChanged(cb_unused wxCommandEvent& event)
4297 {
4298 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4299 if (ed)
4300 ed->GotoNextChanged();
4301 }
4302
OnSearchGotoPrevChanged(cb_unused wxCommandEvent & event)4303 void MainFrame::OnSearchGotoPrevChanged(cb_unused wxCommandEvent& event)
4304 {
4305 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4306 if (ed)
4307 ed->GotoPreviousChanged();
4308 }
4309
OnHelpAbout(wxCommandEvent & WXUNUSED (event))4310 void MainFrame::OnHelpAbout(wxCommandEvent& WXUNUSED(event))
4311 {
4312 dlgAbout dlg(this);
4313 PlaceWindow(&dlg, pdlHead);
4314 dlg.ShowModal();
4315 }
4316
OnHelpTips(cb_unused wxCommandEvent & event)4317 void MainFrame::OnHelpTips(cb_unused wxCommandEvent& event)
4318 {
4319 ShowTips(true);
4320 }
4321
OnFileMenuUpdateUI(wxUpdateUIEvent & event)4322 void MainFrame::OnFileMenuUpdateUI(wxUpdateUIEvent& event)
4323 {
4324 if (Manager::IsAppShuttingDown())
4325 {
4326 event.Skip();
4327 return;
4328 }
4329
4330 if (!ProjectManager::CanShutdown() || !EditorManager::CanShutdown())
4331 {
4332 event.Enable(false);
4333 return;
4334 }
4335
4336 EditorManager *editorManager = Manager::Get()->GetEditorManager();
4337 EditorBase *ed = (editorManager ? editorManager->GetActiveEditor() : nullptr);
4338 EditorBase *sh = (editorManager ? editorManager->GetEditor(g_StartHereTitle) : nullptr);
4339
4340 const int id = event.GetId();
4341
4342 // Single file related menu items
4343 if (id == idFileClose || id == idFileCloseAll || id == idFileSaveAs)
4344 event.Enable(ed && ed != sh);
4345 else if (id == idFileSave)
4346 event.Enable(ed && ed->GetModified());
4347 else if (id == idFilePrint)
4348 event.Enable(editorManager && editorManager->GetBuiltinActiveEditor());
4349 else if (id == idFileOpen)
4350 event.Enable(true);
4351 else
4352 {
4353 ProjectManager *projectManager = Manager::Get()->GetProjectManager();
4354 cbProject *project = (projectManager ? projectManager->GetActiveProject() : nullptr);
4355 if (project && project->GetCurrentlyCompilingTarget())
4356 {
4357 event.Enable(false);
4358 return;
4359 }
4360
4361 // Project related menu items
4362 if (id == idFileReopenProject)
4363 event.Enable(true);
4364 else if (id == idFileCloseProject || id == idFileSaveProjectAs || id == idFileSaveProjectTemplate)
4365 event.Enable(project != nullptr);
4366 else if (id == idFileSaveProject)
4367 event.Enable(project && project->GetModified());
4368 else if (id == idFileOpenDefWorkspace || id == idFileSaveWorkspaceAs || id == idFileSaveAll)
4369 event.Enable(true);
4370 else
4371 {
4372 // Workspace related menu items
4373 const cbWorkspace *workspace = Manager::Get()->GetProjectManager()->GetWorkspace();
4374
4375 if (id == idFileSaveWorkspace)
4376 event.Enable(workspace && workspace->GetModified());
4377 else if (id == idFileCloseWorkspace)
4378 event.Enable(workspace != nullptr);
4379 else
4380 event.Skip();
4381 }
4382 }
4383 }
4384
OnEditMenuUpdateUI(wxUpdateUIEvent & event)4385 void MainFrame::OnEditMenuUpdateUI(wxUpdateUIEvent& event)
4386 {
4387 if (Manager::IsAppShuttingDown())
4388 {
4389 event.Skip();
4390 return;
4391 }
4392
4393 cbEditor* ed = NULL;
4394 EditorBase* eb = NULL;
4395 bool hasSel = false;
4396 bool canUndo = false;
4397 bool canRedo = false;
4398 bool canPaste = false;
4399 bool canCut = false;
4400 bool canSelAll = false;
4401
4402 if (Manager::Get()->GetEditorManager() && !Manager::IsAppShuttingDown())
4403 {
4404 ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4405 eb = Manager::Get()->GetEditorManager()->GetActiveEditor();
4406 }
4407
4408 wxMenuBar* mbar = GetMenuBar();
4409
4410 if (eb)
4411 {
4412 canUndo = eb->CanUndo();
4413 canRedo = eb->CanRedo();
4414 hasSel = eb->HasSelection();
4415 canPaste = eb->CanPaste();
4416 canCut = !eb->IsReadOnly() && hasSel;
4417 canSelAll = eb->CanSelectAll();
4418 }
4419
4420 mbar->Enable(idEditUndo, canUndo);
4421 mbar->Enable(idEditRedo, canRedo);
4422 mbar->Enable(idEditClearHistory, canUndo || canRedo);
4423 mbar->Enable(idEditCut, canCut);
4424 mbar->Enable(idEditCopy, hasSel);
4425 mbar->Enable(idEditPaste, canPaste);
4426 mbar->Enable(idEditSwapHeaderSource, ed);
4427 mbar->Enable(idEditGotoMatchingBrace, ed);
4428 mbar->Enable(idEditHighlightMode, ed);
4429 mbar->Enable(idEditSelectAll, canSelAll);
4430 mbar->Enable(idEditSelectNext, ed);
4431 mbar->Enable(idEditSelectNextSkip, hasSel);
4432 mbar->Enable(idEditBookmarks, ed);
4433 mbar->Enable(idEditFolding, ed &&
4434 Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/folding/show_folds"), false));
4435 mbar->Enable(idEditEOLMode, ed);
4436 mbar->Enable(idEditEncoding, ed);
4437 mbar->Enable(idEditSpecialCommands, ed);
4438 mbar->Enable(idEditSpecialCommandsCase, ed && hasSel);
4439 mbar->Enable(idEditCommentSelected, ed);
4440 mbar->Enable(idEditUncommentSelected, ed);
4441 mbar->Enable(idEditToggleCommentSelected, ed);
4442 mbar->Enable(idEditStreamCommentSelected, ed);
4443 mbar->Enable(idEditBoxCommentSelected, ed);
4444 mbar->Enable(idEditShowCallTip, ed);
4445 mbar->Enable(idEditCompleteCode, ed);
4446
4447 if (ed)
4448 {
4449 // OK... this was the strangest/silliest/most-frustrating bug ever in the computer programs history...
4450 // Under wxGTK it seems that if you try to Check() a menu item if its container Menu is disabled,
4451 // you enter an endless message loop eating 100% CPU...
4452 // DARN!
4453 // This fixes the dreaded 'linux-hang-on-close-project' bug.
4454
4455 switch (ed->GetControl()->GetEOLMode())
4456 {
4457 case wxSCI_EOL_CRLF:
4458 mbar->Check(idEditEOLCRLF, true);
4459 break;
4460 case wxSCI_EOL_CR:
4461 mbar->Check(idEditEOLCR, true);
4462 break;
4463 case wxSCI_EOL_LF:
4464 mbar->Check(idEditEOLLF, true);
4465 break;
4466 default:
4467 (platform::windows ? mbar->Check(idEditEOLCRLF, true) : mbar->Check(idEditEOLLF, true));
4468 break;
4469 }
4470
4471 bool defenc = ed && ( ed->GetEncoding() == wxFONTENCODING_SYSTEM
4472 || ed->GetEncoding() == wxLocale::GetSystemEncoding() );
4473
4474 mbar->Check(idEditEncodingDefault, defenc);
4475 mbar->Check(idEditEncodingUseBom, ed && ed->GetUseBom());
4476 mbar->Check(idEditEncodingAscii, ed && ed->GetEncoding() == wxFONTENCODING_ISO8859_1);
4477 mbar->Check(idEditEncodingUtf7, ed && ed->GetEncoding() == wxFONTENCODING_UTF7);
4478 mbar->Check(idEditEncodingUtf8, ed && ed->GetEncoding() == wxFONTENCODING_UTF8);
4479 mbar->Check(idEditEncodingUnicode, ed && ed->GetEncoding() == wxFONTENCODING_UNICODE);
4480 mbar->Check(idEditEncodingUtf16, ed && ed->GetEncoding() == wxFONTENCODING_UTF16);
4481 mbar->Check(idEditEncodingUtf32, ed && ed->GetEncoding() == wxFONTENCODING_UTF32);
4482 mbar->Check(idEditEncodingUnicode16BE, ed && ed->GetEncoding() == wxFONTENCODING_UTF16BE);
4483 mbar->Check(idEditEncodingUnicode16LE, ed && ed->GetEncoding() == wxFONTENCODING_UTF16LE);
4484 mbar->Check(idEditEncodingUnicode32BE, ed && ed->GetEncoding() == wxFONTENCODING_UTF32BE);
4485 mbar->Check(idEditEncodingUnicode32LE, ed && ed->GetEncoding() == wxFONTENCODING_UTF32LE);
4486
4487 wxMenu* hl = nullptr;
4488 mbar->FindItem(idEditHighlightModeText, &hl);
4489 if (hl)
4490 {
4491 EditorColourSet* colour_set = ed->GetColourSet();
4492 if (colour_set)
4493 {
4494 int item = hl->FindItem(colour_set->GetLanguageName(ed->GetLanguage()));
4495 if (item != wxNOT_FOUND)
4496 mbar->Check(item, true);
4497 }
4498 }
4499 }
4500
4501 if (m_pToolbar)
4502 {
4503 m_pToolbar->EnableTool(idEditUndo, canUndo);
4504 m_pToolbar->EnableTool(idEditRedo, canRedo);
4505 m_pToolbar->EnableTool(idEditCut, canCut);
4506 m_pToolbar->EnableTool(idEditCopy, hasSel);
4507 m_pToolbar->EnableTool(idEditPaste, canPaste);
4508 }
4509
4510 event.Skip();
4511 }
4512
OnViewMenuUpdateUI(wxUpdateUIEvent & event)4513 void MainFrame::OnViewMenuUpdateUI(wxUpdateUIEvent& event)
4514 {
4515 if (Manager::IsAppShuttingDown())
4516 {
4517 event.Skip();
4518 return;
4519 }
4520
4521 wxMenuBar* mbar = GetMenuBar();
4522 cbEditor* ed = Manager::Get()->GetEditorManager() ? Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor() : nullptr;
4523 bool manVis = m_LayoutManager.GetPane(m_pPrjManUI->GetNotebook()).IsShown();
4524
4525 mbar->Check(idViewManager, manVis);
4526 mbar->Check(idViewLogManager, m_LayoutManager.GetPane(m_pInfoPane).IsShown());
4527 mbar->Check(idViewStartPage, Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle)!=NULL);
4528 mbar->Check(idViewStatusbar, GetStatusBar() && GetStatusBar()->IsShown());
4529 mbar->Check(idViewScriptConsole, m_LayoutManager.GetPane(m_pScriptConsole).IsShown());
4530 mbar->Check(idViewHideEditorTabs, Manager::Get()->GetEditorManager()->GetNotebook()->GetTabCtrlHeight() == 0);
4531 mbar->Check(idViewFullScreen, IsFullScreen());
4532 mbar->Enable(idViewFocusEditor, ed);
4533 mbar->Enable(idViewFocusManagement, manVis);
4534 mbar->Enable(idViewFocusLogsAndOthers, m_pInfoPane->IsShown());
4535
4536 // toolbars
4537 wxMenu* viewToolbars = nullptr;
4538 GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
4539 if (viewToolbars)
4540 {
4541 SetChecksForViewToolbarsMenu(*viewToolbars);
4542 }
4543
4544 event.Skip();
4545 }
4546
OnSearchMenuUpdateUI(wxUpdateUIEvent & event)4547 void MainFrame::OnSearchMenuUpdateUI(wxUpdateUIEvent& event)
4548 {
4549 if (Manager::IsAppShuttingDown())
4550 {
4551 event.Skip();
4552 return;
4553 }
4554
4555 cbEditor* ed = Manager::Get()->GetEditorManager()
4556 ? Manager::Get()->GetEditorManager()->GetBuiltinEditor(
4557 Manager::Get()->GetEditorManager()->GetActiveEditor() ) : nullptr;
4558
4559 bool enableGoto = false;
4560 if (ed)
4561 enableGoto = Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true)
4562 && (ed->CanUndo() || ed->CanRedo());
4563
4564 wxMenuBar* mbar = GetMenuBar();
4565
4566 // 'Find' and 'Replace' are always enabled for (find|replace)-in-files
4567 // (idSearchFindInFiles and idSearchReplaceInFiles)
4568
4569 mbar->Enable(idSearchFind, ed);
4570 mbar->Enable(idSearchFindNext, ed);
4571 mbar->Enable(idSearchFindPrevious, ed);
4572 mbar->Enable(idSearchFindSelectedNext, ed);
4573 mbar->Enable(idSearchFindSelectedPrevious, ed);
4574 mbar->Enable(idSearchReplace, ed);
4575 mbar->Enable(idSearchGotoLine, ed);
4576 mbar->Enable(idSearchGotoNextChanged, enableGoto);
4577 mbar->Enable(idSearchGotoPreviousChanged, enableGoto);
4578
4579 event.Skip();
4580 }
4581
4582
OnEditorUpdateUI(CodeBlocksEvent & event)4583 void MainFrame::OnEditorUpdateUI(CodeBlocksEvent& event)
4584 {
4585 if (Manager::IsAppShuttingDown())
4586 {
4587 event.Skip();
4588 return;
4589 }
4590
4591 if (Manager::Get()->GetEditorManager() && event.GetEditor() == Manager::Get()->GetEditorManager()->GetActiveEditor())
4592 {
4593 #if wxCHECK_VERSION(3, 0, 0)
4594 // Execute the code to update the status bar outside of the paint event for scintilla.
4595 // Executing this function directly in the event handler causes redraw problems on Windows.
4596 CallAfter(&MainFrame::DoUpdateStatusBar);
4597 #else
4598 DoUpdateStatusBar();
4599 #endif // defined(__wxMSW__) && wxCHECK_VERSION(3, 0, 0)
4600 }
4601
4602 event.Skip();
4603 }
4604
OnViewToolbarsFit(cb_unused wxCommandEvent & event)4605 void MainFrame::OnViewToolbarsFit(cb_unused wxCommandEvent& event)
4606 {
4607 FitToolbars(m_LayoutManager, this);
4608 DoUpdateLayout();
4609 }
4610
OnViewToolbarsOptimize(cb_unused wxCommandEvent & event)4611 void MainFrame::OnViewToolbarsOptimize(cb_unused wxCommandEvent& event)
4612 {
4613 OptimizeToolbars(m_LayoutManager, this);
4614 DoUpdateLayout();
4615 }
4616
OnToggleBar(wxCommandEvent & event)4617 void MainFrame::OnToggleBar(wxCommandEvent& event)
4618 {
4619 wxWindow* win = nullptr;
4620 bool toolbar = false;
4621 if (event.GetId() == idViewManager)
4622 win = m_pPrjManUI->GetNotebook();
4623 else if (event.GetId() == idViewLogManager)
4624 win = m_pInfoPane;
4625 else if (event.GetId() == idViewToolMain)
4626 {
4627 win = m_pToolbar;
4628 toolbar = true;
4629 }
4630 else if (event.GetId() == idViewToolDebugger)
4631 {
4632 win = m_debuggerToolbarHandler->GetToolbar();
4633 toolbar = true;
4634 }
4635 else
4636 {
4637 wxString pluginName = m_PluginIDsMap[event.GetId()];
4638 if (!pluginName.IsEmpty())
4639 {
4640 cbPlugin* plugin = Manager::Get()->GetPluginManager()->FindPluginByName(pluginName);
4641 if (plugin)
4642 {
4643 win = m_PluginsTools[plugin];
4644 toolbar = true;
4645 }
4646 }
4647 }
4648
4649 if (win)
4650 {
4651 // For checked menu items, event.IsChecked() will not reflect the actual status of the menu item
4652 // when this event was previously event.Skip()'ed after the menu item change.
4653 bool isShown = m_LayoutManager.GetPane(win).IsShown();
4654
4655 // use last visible size as BestSize, Logs & others does no longer "forget" it's size
4656 if (!isShown)
4657 m_LayoutManager.GetPane(win).BestSize(win->GetSize());
4658
4659 m_LayoutManager.GetPane(win).Show(not isShown); //toggle
4660 if (toolbar)
4661 FitToolbars(m_LayoutManager, this);
4662 DoUpdateLayout();
4663 }
4664 }
4665
OnToggleStatusBar(cb_unused wxCommandEvent & event)4666 void MainFrame::OnToggleStatusBar(cb_unused wxCommandEvent& event)
4667 {
4668 cbStatusBar* sb = (cbStatusBar*)GetStatusBar();
4669 if (!sb) return;
4670
4671 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
4672 const bool show = !cfg->ReadBool(_T("/main_frame/statusbar"), true);
4673 cfg->Write(_T("/main_frame/statusbar"), show);
4674
4675 DoUpdateStatusBar();
4676 sb->Show(show);
4677 if ( show ) SendSizeEvent();
4678 DoUpdateLayout();
4679 }
4680
OnFocusEditor(cb_unused wxCommandEvent & event)4681 void MainFrame::OnFocusEditor(cb_unused wxCommandEvent& event)
4682 {
4683 EditorManager* edman = Manager::Get()->GetEditorManager();
4684 cbAuiNotebook* nb = edman?edman->GetNotebook():nullptr;
4685 if (nb)
4686 nb->FocusActiveTabCtrl();
4687 }
4688
OnFocusManagement(cb_unused wxCommandEvent & event)4689 void MainFrame::OnFocusManagement(cb_unused wxCommandEvent& event)
4690 {
4691 cbAuiNotebook* nb = m_pPrjManUI ? m_pPrjManUI->GetNotebook() : nullptr;
4692 if (nb)
4693 nb->FocusActiveTabCtrl();
4694 }
4695
OnFocusLogsAndOthers(cb_unused wxCommandEvent & event)4696 void MainFrame::OnFocusLogsAndOthers(cb_unused wxCommandEvent& event)
4697 {
4698 if (m_pInfoPane)
4699 m_pInfoPane->FocusActiveTabCtrl();
4700 }
4701
OnSwitchTabs(cb_unused wxCommandEvent & event)4702 void MainFrame::OnSwitchTabs(cb_unused wxCommandEvent& event)
4703 {
4704 // Get the notebook from the editormanager:
4705 cbAuiNotebook* nb = Manager::Get()->GetEditorManager()->GetNotebook();
4706 if (!nb)
4707 return;
4708
4709 // Create container and add all open editors:
4710 wxSwitcherItems items;
4711 items.AddGroup(_("Open files"), wxT("editors"));
4712 if (!Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/tabs_stacked_based_switching")))
4713 { // Switch tabs editor with tab order
4714 for (size_t i = 0; i < nb->GetPageCount(); ++i)
4715 {
4716 wxString title = nb->GetPageText(i);
4717 wxWindow* window = nb->GetPage(i);
4718
4719 items.AddItem(title, title, GetEditorDescription(static_cast<EditorBase*> (window)), i, nb->GetPageBitmap(i)).SetWindow(window);
4720 }
4721
4722 // Select the focused editor:
4723 int idx = items.GetIndexForFocus();
4724 if (idx != wxNOT_FOUND)
4725 items.SetSelection(idx);
4726 }
4727 else
4728 { // Switch tabs editor with last used order
4729 int index = 0;
4730 cbNotebookStack* body;
4731 for (body = Manager::Get()->GetEditorManager()->GetNotebookStack(); body != NULL; body = body->next)
4732 {
4733 index = nb->GetPageIndex(body->window);
4734 if (index == wxNOT_FOUND)
4735 continue;
4736 wxString title = nb->GetPageText(index);
4737 items.AddItem(title, title, GetEditorDescription(static_cast<EditorBase*> (body->window)), index, nb->GetPageBitmap(index)).SetWindow(body->window);
4738 }
4739
4740 // Select the focused editor:
4741 if(items.GetItemCount() > 2)
4742 items.SetSelection(2); // CTRL + TAB directly select the last editor, not the current one
4743 else
4744 items.SetSelection(items.GetItemCount()-1);
4745 }
4746
4747 // Create the switcher dialog
4748 wxSwitcherDialog dlg(items, wxGetApp().GetTopWindow());
4749
4750 // Ctrl+Tab workaround for non windows platforms:
4751 if (platform::cocoa)
4752 dlg.SetModifierKey(WXK_ALT);
4753 else if (platform::gtk)
4754 dlg.SetExtraNavigationKey(wxT(','));
4755
4756 // Finally show the dialog:
4757 int answer = dlg.ShowModal();
4758
4759 // If necessary change the selected editor:
4760 if ((answer == wxID_OK) && (dlg.GetSelection() != -1))
4761 {
4762 wxSwitcherItem& item = items.GetItem(dlg.GetSelection());
4763 wxWindow* win = item.GetWindow();
4764 if (win)
4765 {
4766 nb->SetSelection(item.GetId());
4767 win->SetFocus();
4768 }
4769 }
4770 }
4771
OnToggleStartPage(cb_unused wxCommandEvent & event)4772 void MainFrame::OnToggleStartPage(cb_unused wxCommandEvent& event)
4773 {
4774
4775 int toggle=-1;
4776 if(Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle)==NULL)
4777 {
4778 toggle=1;
4779 }
4780 ShowHideStartPage(false,toggle);
4781 }
4782
OnToggleFullScreen(cb_unused wxCommandEvent & event)4783 void MainFrame::OnToggleFullScreen(cb_unused wxCommandEvent& event)
4784 {
4785 ShowFullScreen( !IsFullScreen(), wxFULLSCREEN_NOTOOLBAR// | wxFULLSCREEN_NOSTATUSBAR
4786 | wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION );
4787
4788 // Create full screen-close button if we're in full screen
4789 if ( IsFullScreen() )
4790 {
4791 //
4792 // Show the button to the bottom-right of the container
4793 //
4794 wxSize containerSize = GetClientSize();
4795 wxSize buttonSize = m_pCloseFullScreenBtn->GetSize();
4796
4797 // Align
4798 m_pCloseFullScreenBtn->Move( containerSize.GetWidth() - buttonSize.GetWidth(),
4799 containerSize.GetHeight() - buttonSize.GetHeight() );
4800
4801 m_pCloseFullScreenBtn->Show( true );
4802 m_pCloseFullScreenBtn->Raise();
4803 }
4804 else
4805 m_pCloseFullScreenBtn->Show( false );
4806 }
4807
OnPluginInstalled(CodeBlocksEvent & event)4808 void MainFrame::OnPluginInstalled(CodeBlocksEvent& event)
4809 {
4810 PluginsUpdated(event.GetPlugin(), Installed);
4811 }
4812
OnPluginUninstalled(CodeBlocksEvent & event)4813 void MainFrame::OnPluginUninstalled(CodeBlocksEvent& event)
4814 {
4815 if (Manager::IsAppShuttingDown())
4816 return;
4817 PluginsUpdated(event.GetPlugin(), Uninstalled);
4818 }
4819
OnPluginLoaded(CodeBlocksEvent & event)4820 void MainFrame::OnPluginLoaded(CodeBlocksEvent& event)
4821 {
4822 cbPlugin* plug = event.GetPlugin();
4823 if (plug)
4824 {
4825 DoAddPlugin(plug);
4826 const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plug);
4827 wxString msg = info ? info->title : wxString(_("<Unknown plugin>"));
4828 Manager::Get()->GetLogManager()->DebugLog(F(_T("%s plugin activated"), msg.wx_str()));
4829 }
4830 }
4831
OnPluginUnloaded(CodeBlocksEvent & event)4832 void MainFrame::OnPluginUnloaded(CodeBlocksEvent& event)
4833 {
4834 if (Manager::IsAppShuttingDown())
4835 return;
4836
4837 cbPlugin* plugin = event.GetPlugin();
4838
4839 cbStatusBar *sb = (cbStatusBar*)GetStatusBar();
4840 if ( sb )
4841 sb->RemoveField(plugin);
4842
4843 // remove toolbar, if any
4844 if (m_PluginsTools[plugin])
4845 {
4846 // Disconnect the mouse right click event handler before the toolbar is destroyed
4847 bool result = m_PluginsTools[plugin]->Disconnect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick));
4848 cbAssert(result);
4849 m_LayoutManager.DetachPane(m_PluginsTools[plugin]);
4850 m_PluginsTools[plugin]->Destroy();
4851 m_PluginsTools.erase(plugin);
4852 DoUpdateLayout();
4853 }
4854
4855 PluginsUpdated(plugin, Unloaded);
4856 }
4857
OnSettingsEnvironment(cb_unused wxCommandEvent & event)4858 void MainFrame::OnSettingsEnvironment(cb_unused wxCommandEvent& event)
4859 {
4860 bool needRestart = false;
4861 const int originalToolbarSize = cbHelpers::ReadToolbarSizeFromConfig();
4862
4863 EnvironmentSettingsDlg dlg(this, m_LayoutManager.GetArtProvider());
4864 PlaceWindow(&dlg);
4865 if (dlg.ShowModal() == wxID_OK)
4866 {
4867 DoUpdateEditorStyle();
4868 DoUpdateLayoutColours();
4869
4870 {
4871 ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
4872 const int newToolbarSize = cfg->ReadInt(_T("/environment/toolbar_size"),
4873 cbHelpers::defaultToolbarSize);
4874 needRestart = (newToolbarSize != originalToolbarSize);
4875 }
4876
4877 Manager::Get()->GetLogManager()->NotifyUpdate();
4878 Manager::Get()->GetEditorManager()->RecreateOpenEditorStyles();
4879 Manager::Get()->GetCCManager()->UpdateEnvSettings();
4880 m_pPrjManUI->RebuildTree();
4881 ShowHideStartPage();
4882
4883 CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4884 event2.SetInt(cbSettingsType::Environment);
4885 Manager::Get()->ProcessEvent(event2);
4886 }
4887 if (needRestart)
4888 cbMessageBox(_("Code::Blocks needs to be restarted for the changes to take effect."), _("Information"), wxICON_INFORMATION);
4889 }
4890
OnGlobalUserVars(cb_unused wxCommandEvent & event)4891 void MainFrame::OnGlobalUserVars(cb_unused wxCommandEvent& event)
4892 {
4893 Manager::Get()->GetUserVariableManager()->Configure();
4894 }
4895
OnSettingsEditor(cb_unused wxCommandEvent & event)4896 void MainFrame::OnSettingsEditor(cb_unused wxCommandEvent& event)
4897 {
4898 // editor lexers loading takes some time; better reflect this with a hourglass
4899 wxBeginBusyCursor();
4900
4901 EditorConfigurationDlg dlg(Manager::Get()->GetAppWindow());
4902 PlaceWindow(&dlg);
4903
4904 // done, restore pointer
4905 wxEndBusyCursor();
4906
4907 if (dlg.ShowModal() == wxID_OK)
4908 {
4909 Manager::Get()->GetEditorManager()->RecreateOpenEditorStyles();
4910
4911 CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4912 event2.SetInt(cbSettingsType::Editor);
4913 Manager::Get()->ProcessEvent(event2);
4914 }
4915 }
4916
OnSettingsCompiler(cb_unused wxCommandEvent & event)4917 void MainFrame::OnSettingsCompiler(cb_unused wxCommandEvent& event)
4918 {
4919 CompilerSettingsDlg dlg(this);
4920 PlaceWindow(&dlg);
4921 if (dlg.ShowModal() == wxID_OK)
4922 {
4923 CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4924 event2.SetInt(cbSettingsType::Compiler);
4925 Manager::Get()->ProcessEvent(event2);
4926 }
4927 }
4928
OnSettingsDebugger(cb_unused wxCommandEvent & event)4929 void MainFrame::OnSettingsDebugger(cb_unused wxCommandEvent& event)
4930 {
4931 DebuggerSettingsDlg dlg(this);
4932 PlaceWindow(&dlg);
4933 if (dlg.ShowModal() == wxID_OK)
4934 {
4935 CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4936 event2.SetInt(cbSettingsType::Debugger);
4937 Manager::Get()->ProcessEvent(event2);
4938 }
4939 }
4940
OnSettingsPlugins(cb_unused wxCommandEvent & event)4941 void MainFrame::OnSettingsPlugins(cb_unused wxCommandEvent& event)
4942 {
4943 if (Manager::Get()->GetPluginManager()->Configure() == wxID_OK)
4944 {
4945 CodeBlocksEvent event2(cbEVT_SETTINGS_CHANGED);
4946 event2.SetInt(cbSettingsType::Plugins);
4947 Manager::Get()->ProcessEvent(event2);
4948 }
4949 }
4950
OnSettingsScripting(cb_unused wxCommandEvent & event)4951 void MainFrame::OnSettingsScripting(cb_unused wxCommandEvent& event)
4952 {
4953 ScriptingSettingsDlg dlg(this);
4954 if (dlg.ShowModal() == wxID_OK)
4955 RunStartupScripts();
4956 }
4957
OnProjectActivated(CodeBlocksEvent & event)4958 void MainFrame::OnProjectActivated(CodeBlocksEvent& event)
4959 {
4960 DoUpdateAppTitle();
4961 event.Skip();
4962 }
4963
OnProjectOpened(CodeBlocksEvent & event)4964 void MainFrame::OnProjectOpened(CodeBlocksEvent& event)
4965 {
4966 ShowHideStartPage(true);
4967 event.Skip();
4968 }
4969
OnEditorOpened(CodeBlocksEvent & event)4970 void MainFrame::OnEditorOpened(CodeBlocksEvent& event)
4971 {
4972 DoUpdateAppTitle();
4973 event.Skip();
4974 }
4975
OnEditorActivated(CodeBlocksEvent & event)4976 void MainFrame::OnEditorActivated(CodeBlocksEvent& event)
4977 {
4978 DoUpdateAppTitle();
4979 DoUpdateStatusBar();
4980
4981 EditorBase *editor = event.GetEditor();
4982 if (editor && editor->IsBuiltinEditor())
4983 {
4984 ConfigManager* cfgEditor = Manager::Get()->GetConfigManager(_T("editor"));
4985 if (cfgEditor->ReadBool(_T("/sync_editor_with_project_manager"), false))
4986 {
4987 ProjectFile* pf = static_cast<cbEditor*>(editor)->GetProjectFile();
4988 if (pf)
4989 m_pPrjManUI->ShowFileInTree(*pf);
4990 }
4991 }
4992
4993 event.Skip();
4994 }
4995
OnEditorClosed(CodeBlocksEvent & event)4996 void MainFrame::OnEditorClosed(CodeBlocksEvent& event)
4997 {
4998 DoUpdateAppTitle();
4999 DoUpdateStatusBar();
5000 event.Skip();
5001 }
5002
OnEditorSaved(CodeBlocksEvent & event)5003 void MainFrame::OnEditorSaved(CodeBlocksEvent& event)
5004 {
5005 DoUpdateAppTitle();
5006 event.Skip();
5007 }
5008
OnEditorModified(CodeBlocksEvent & event)5009 void MainFrame::OnEditorModified(CodeBlocksEvent& event)
5010 {
5011 DoUpdateAppTitle();
5012 event.Skip();
5013 }
5014
OnProjectClosed(CodeBlocksEvent & event)5015 void MainFrame::OnProjectClosed(CodeBlocksEvent& event)
5016 {
5017 ShowHideStartPage();
5018 event.Skip();
5019 }
5020
OnPageChanged(wxNotebookEvent & event)5021 void MainFrame::OnPageChanged(wxNotebookEvent& event)
5022 {
5023 DoUpdateAppTitle();
5024 event.Skip();
5025 }
5026
OnShiftTab(cb_unused wxCommandEvent & event)5027 void MainFrame::OnShiftTab(cb_unused wxCommandEvent& event)
5028 {
5029 // Must make sure it's cbEditor and not EditorBase
5030 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
5031 if (ed)
5032 ed->DoUnIndent();
5033 }
5034
OnCtrlAltTab(cb_unused wxCommandEvent & event)5035 void MainFrame::OnCtrlAltTab(cb_unused wxCommandEvent& event)
5036 {
5037 wxCommandEvent dummy;
5038 switch (m_LastCtrlAltTabWindow)
5039 {
5040 case 1: // Focus is on the Mgmt. panel -> Cycle to Editor
5041 m_LastCtrlAltTabWindow = 2;
5042 OnFocusEditor(dummy);
5043 break;
5044 case 2: // Focus is on the Editor -> Cycle to Logs & others
5045 m_LastCtrlAltTabWindow = 3;
5046 OnFocusLogsAndOthers(dummy);
5047 break;
5048 case 3: // Focus is on Logs & others -> fall through
5049 default: // Focus (cycle to) the Mgmt. panel
5050 m_LastCtrlAltTabWindow = 1;
5051 OnFocusManagement(dummy);
5052 }
5053 }
5054
OnRequestDockWindow(CodeBlocksDockEvent & event)5055 void MainFrame::OnRequestDockWindow(CodeBlocksDockEvent& event)
5056 {
5057 if (Manager::IsAppShuttingDown())
5058 return;
5059
5060 wxAuiPaneInfo info;
5061 wxString name = event.name;
5062 if (name.IsEmpty())
5063 {
5064 static int idx = 0;
5065 name = wxString::Format(_T("UntitledPane%d"), ++idx);
5066 }
5067 // TODO (mandrav##): Check for existing pane with the same name
5068 info.Name(name);
5069 info.Caption(event.title.IsEmpty() ? name : event.title);
5070 switch (event.dockSide)
5071 {
5072 case CodeBlocksDockEvent::dsLeft: info.Left(); break;
5073 case CodeBlocksDockEvent::dsRight: info.Right(); break;
5074 case CodeBlocksDockEvent::dsTop: info.Top(); break;
5075 case CodeBlocksDockEvent::dsBottom: info.Bottom(); break;
5076 case CodeBlocksDockEvent::dsFloating: info.Float(); break;
5077 case CodeBlocksDockEvent::dsUndefined: // fall through
5078 default: break;
5079 }
5080 info.Show(event.shown);
5081 info.BestSize(event.desiredSize);
5082 info.FloatingSize(event.floatingSize);
5083 info.FloatingPosition(event.floatingPos);
5084 info.MinSize(event.minimumSize);
5085 info.Layer(event.stretch ? 1 : 0);
5086
5087 if (event.row != -1)
5088 info.Row(event.row);
5089 if (event.column != -1)
5090 info.Position(event.column);
5091 info.CloseButton(event.hideable ? true : false);
5092 m_LayoutManager.AddPane(event.pWindow, info);
5093 DoUpdateLayout();
5094 }
5095
OnRequestUndockWindow(CodeBlocksDockEvent & event)5096 void MainFrame::OnRequestUndockWindow(CodeBlocksDockEvent& event)
5097 {
5098 wxAuiPaneInfo info = m_LayoutManager.GetPane(event.pWindow);
5099 if (info.IsOk())
5100 {
5101 m_LayoutManager.DetachPane(event.pWindow);
5102 DoUpdateLayout();
5103 }
5104 }
5105
OnRequestShowDockWindow(CodeBlocksDockEvent & event)5106 void MainFrame::OnRequestShowDockWindow(CodeBlocksDockEvent& event)
5107 {
5108 m_LayoutManager.GetPane(event.pWindow).Show();
5109 DoUpdateLayout();
5110
5111 CodeBlocksDockEvent evt(cbEVT_DOCK_WINDOW_VISIBILITY);
5112 evt.pWindow = event.pWindow;
5113 Manager::Get()->ProcessEvent(evt);
5114 }
5115
OnRequestHideDockWindow(CodeBlocksDockEvent & event)5116 void MainFrame::OnRequestHideDockWindow(CodeBlocksDockEvent& event)
5117 {
5118 m_LayoutManager.GetPane(event.pWindow).Hide();
5119 DoUpdateLayout();
5120
5121 CodeBlocksDockEvent evt(cbEVT_DOCK_WINDOW_VISIBILITY);
5122 evt.pWindow = event.pWindow;
5123 Manager::Get()->ProcessEvent(evt);
5124 }
5125
OnDockWindowVisibility(cb_unused CodeBlocksDockEvent & event)5126 void MainFrame::OnDockWindowVisibility(cb_unused CodeBlocksDockEvent& event)
5127 {
5128 // if (m_ScriptConsoleID != -1 && event.GetId() == m_ScriptConsoleID)
5129 // ShowHideScriptConsole();
5130 }
5131
OnLayoutUpdate(cb_unused CodeBlocksLayoutEvent & event)5132 void MainFrame::OnLayoutUpdate(cb_unused CodeBlocksLayoutEvent& event)
5133 {
5134 DoUpdateLayout();
5135 }
5136
OnLayoutQuery(CodeBlocksLayoutEvent & event)5137 void MainFrame::OnLayoutQuery(CodeBlocksLayoutEvent& event)
5138 {
5139 event.layout = !m_LastLayoutName.IsEmpty() ? m_LastLayoutName : gDefaultLayout;
5140 event.StopPropagation();
5141 }
5142
OnLayoutSwitch(CodeBlocksLayoutEvent & event)5143 void MainFrame::OnLayoutSwitch(CodeBlocksLayoutEvent& event)
5144 {
5145 LoadViewLayout(event.layout, true);
5146 }
5147
OnAddLogWindow(CodeBlocksLogEvent & event)5148 void MainFrame::OnAddLogWindow(CodeBlocksLogEvent& event)
5149 {
5150 if (Manager::IsAppShuttingDown())
5151 return;
5152 wxWindow* p = event.window;
5153 if (p)
5154 m_pInfoPane->AddNonLogger(p, event.title, event.icon);
5155 else
5156 {
5157 p = event.logger->CreateControl(m_pInfoPane);
5158 if (p)
5159 m_pInfoPane->AddLogger(event.logger, p, event.title, event.icon);
5160 }
5161 Manager::Get()->GetLogManager()->NotifyUpdate();
5162 }
5163
OnRemoveLogWindow(CodeBlocksLogEvent & event)5164 void MainFrame::OnRemoveLogWindow(CodeBlocksLogEvent& event)
5165 {
5166 if (Manager::IsAppShuttingDown())
5167 return;
5168 if (event.window)
5169 m_pInfoPane->DeleteNonLogger(event.window);
5170 else
5171 m_pInfoPane->DeleteLogger(event.logger);
5172 }
5173
OnHideLogWindow(CodeBlocksLogEvent & event)5174 void MainFrame::OnHideLogWindow(CodeBlocksLogEvent& event)
5175 {
5176 if (event.window)
5177 m_pInfoPane->HideNonLogger(event.window);
5178 else if (event.logger)
5179 m_pInfoPane->Hide(event.logger);
5180 }
5181
OnSwitchToLogWindow(CodeBlocksLogEvent & event)5182 void MainFrame::OnSwitchToLogWindow(CodeBlocksLogEvent& event)
5183 {
5184 if (event.window)
5185 m_pInfoPane->ShowNonLogger(event.window);
5186 else if (event.logger)
5187 m_pInfoPane->Show(event.logger);
5188 }
5189
OnGetActiveLogWindow(CodeBlocksLogEvent & event)5190 void MainFrame::OnGetActiveLogWindow(CodeBlocksLogEvent& event)
5191 {
5192 bool is_logger;
5193 int page_index = m_pInfoPane->GetCurrentPage(is_logger);
5194
5195 event.logger = nullptr;
5196 event.window = nullptr;
5197
5198 if (is_logger)
5199 event.logger = m_pInfoPane->GetLogger(page_index);
5200 else
5201 event.window = m_pInfoPane->GetWindow(page_index);
5202 }
5203
OnShowLogManager(cb_unused CodeBlocksLogEvent & event)5204 void MainFrame::OnShowLogManager(cb_unused CodeBlocksLogEvent& event)
5205 {
5206 if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false))
5207 return;
5208
5209 m_LayoutManager.GetPane(m_pInfoPane).Show(true);
5210 DoUpdateLayout();
5211 }
5212
OnHideLogManager(cb_unused CodeBlocksLogEvent & event)5213 void MainFrame::OnHideLogManager(cb_unused CodeBlocksLogEvent& event)
5214 {
5215 if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false) ||
5216 m_AutoHideLockCounter > 0)
5217 return;
5218
5219 m_LayoutManager.GetPane(m_pInfoPane).Show(false);
5220 DoUpdateLayout();
5221 }
5222
OnLockLogManager(cb_unused CodeBlocksLogEvent & event)5223 void MainFrame::OnLockLogManager(cb_unused CodeBlocksLogEvent& event)
5224 {
5225 if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false))
5226 return;
5227 ++m_AutoHideLockCounter;
5228 }
5229
OnUnlockLogManager(cb_unused CodeBlocksLogEvent & event)5230 void MainFrame::OnUnlockLogManager(cb_unused CodeBlocksLogEvent& event)
5231 {
5232 if (!Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_hide"), false) &&
5233 m_AutoHideLockCounter > 0)
5234 return;
5235 if (--m_AutoHideLockCounter == 0)
5236 {
5237 m_LayoutManager.GetPane(m_pInfoPane).Show(false);
5238 DoUpdateLayout();
5239 }
5240 }
5241
5242 // Highlight Button
OnHighlightMenu(cb_unused wxCommandEvent & event)5243 void MainFrame::OnHighlightMenu(cb_unused wxCommandEvent& event)
5244 {
5245 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
5246 if (!ed) return;
5247
5248 EditorColourSet* colour_set = Manager::Get()->GetEditorManager()->GetColourSet();
5249 if (!colour_set) return;
5250
5251 wxMenu* hl = nullptr;
5252 GetMenuBar()->FindItem(idEditHighlightModeText, &hl);
5253 if (!hl)
5254 return;
5255
5256 wxMenu mm;
5257 const wxMenuItemList &menuItems = hl->GetMenuItems();
5258
5259 const wxString selectLanguageName = colour_set->GetLanguageName(ed->GetLanguage());
5260
5261 for (size_t ii = 0; ii < menuItems.GetCount(); ++ii)
5262 {
5263 if (ii > 0 && (ii % 20) == 0)
5264 mm.Break(); // break into columns every 20 items
5265
5266 const wxMenuItem *item = menuItems[ii];
5267 wxMenuItem *newItem = mm.Append(item->GetId(), item->GetItemLabel(), item->GetHelp(),
5268 item->GetKind());
5269 if (item->GetItemLabel() == selectLanguageName)
5270 newItem->Check(true);
5271 }
5272
5273 wxRect rect;
5274 GetStatusBar()->GetFieldRect(1, rect);
5275 PopupMenu(&mm, GetStatusBar()->GetPosition() + rect.GetPosition());
5276 }
5277
StartupDone()5278 void MainFrame::StartupDone()
5279 {
5280 m_StartupDone = true;
5281 DoUpdateLayout();
5282 }
5283
OnCreateStatusBar(int number,long style,wxWindowID id,const wxString & name)5284 wxStatusBar* MainFrame::OnCreateStatusBar(int number, long style, wxWindowID id, const wxString& name)
5285 {
5286 cbStatusBar* sb = new cbStatusBar(this, id, style, name);
5287 sb->SetFieldsCount(number);
5288
5289 return sb;
5290 }
5291
5292 // Let the user toggle the toolbar from the context menu
OnMouseRightUp(wxMouseEvent & event)5293 void MainFrame::OnMouseRightUp(wxMouseEvent& event)
5294 {
5295 PopupToggleToolbarMenu();
5296 event.Skip();
5297 }
5298
OnToolBarRightClick(wxCommandEvent & event)5299 void MainFrame::OnToolBarRightClick(wxCommandEvent& event)
5300 {
5301 PopupToggleToolbarMenu();
5302 event.Skip();
5303 }
5304
PopupToggleToolbarMenu()5305 void MainFrame::PopupToggleToolbarMenu()
5306 {
5307 wxMenuBar* menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
5308 int idx = menuBar->FindMenu(_("&View"));
5309 if (idx == wxNOT_FOUND)
5310 return;
5311 wxMenu* viewMenu = menuBar->GetMenu(idx);
5312 idx = viewMenu->FindItem(_("Toolbars"));
5313 if (idx == wxNOT_FOUND)
5314 return;
5315
5316 // Clone the View -> Toolbars menu and show it as popup.
5317 wxMenu* toolbarMenu = viewMenu->FindItem(idx)->GetSubMenu();
5318 wxMenu menu;
5319 for (size_t ii = 0; ii < toolbarMenu->GetMenuItemCount(); ++ii)
5320 {
5321 wxMenuItem *old = toolbarMenu->FindItemByPosition(ii);
5322 if (!old)
5323 continue;
5324 wxMenuItem *item;
5325 item = new wxMenuItem(&menu, old->GetId(), old->GetItemLabelText(), old->GetHelp(), old->GetKind());
5326 menu.Append(item);
5327 }
5328 SetChecksForViewToolbarsMenu(menu);
5329 PopupMenu(&menu);
5330 }
5331
SetChecksForViewToolbarsMenu(wxMenu & menu)5332 void MainFrame::SetChecksForViewToolbarsMenu(wxMenu &menu)
5333 {
5334 for (size_t i = 0; i < menu.GetMenuItemCount(); ++i)
5335 {
5336 wxMenuItem* item = menu.GetMenuItems()[i];
5337 wxString pluginName = m_PluginIDsMap[item->GetId()];
5338 if (!pluginName.IsEmpty())
5339 {
5340 cbPlugin* plugin = Manager::Get()->GetPluginManager()->FindPluginByName(pluginName);
5341 if (plugin)
5342 item->Check(m_LayoutManager.GetPane(m_PluginsTools[plugin]).IsShown());
5343 }
5344 }
5345
5346 menu.Check(idViewToolMain, m_LayoutManager.GetPane(m_pToolbar).IsShown());
5347 menu.Check(idViewToolDebugger, m_LayoutManager.GetPane(m_debuggerToolbarHandler->GetToolbar(false)).IsShown());
5348 }
5349
OnGetGlobalAccels(wxCommandEvent & event)5350 void MainFrame::OnGetGlobalAccels(wxCommandEvent& event)
5351 {
5352 event.SetInt(m_AccelCount);
5353 void* pUserVector = event.GetClientData();
5354
5355 // vector<MyClass*>& v = *reinterpret_cast<vector<MyClass*> *>(voidPointerName);
5356 std::vector<wxAcceleratorEntry>& globalAccels = *reinterpret_cast<std::vector<wxAcceleratorEntry> *>(pUserVector);
5357 event.SetInt(m_AccelCount);
5358 for (size_t ii=0; ii < m_AccelCount; ++ii)
5359 globalAccels.push_back(m_pAccelEntries[ii]);
5360 return;
5361 }
5362