Code::Blocks  SVN r11506
main.cpp
Go to the documentation of this file.
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: 11478 $
6  * $Id: main.cpp 11478 2018-09-29 07:42:16Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/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 "cbauibook.h"
16 #include "cbstyledtextctrl.h"
17 #include "compilersettingsdlg.h"
18 #include "debuggersettingsdlg.h"
19 #include "dlgabout.h"
20 #include "dlgaboutplugin.h"
21 #include "environmentsettingsdlg.h"
22 #include "infopane.h"
23 #include "infowindow.h"
24 #include "main.h"
25 #include "notebookstyles.h"
26 #include "printdlg.h"
27 #include "scriptconsole.h"
28 #include "scriptingsettingsdlg.h"
29 #include "startherepage.h"
30 #include "switcherdlg.h"
31 #include "cbstatusbar.h"
32 #include "loggers.h"
33 
34 #include <wx/display.h>
35 #include <wx/dnd.h>
36 #include <wx/fileconf.h>
37 #include <wx/filename.h>
38 #include <wx/gdicmn.h>
39 #include <wx/printdlg.h>
40 #include <wx/sstream.h>
41 #include <wx/tipdlg.h>
42 #include <wx/tokenzr.h>
43 #include <wx/xrc/xmlres.h>
44 
45 #include <annoyingdialog.h>
46 #include <cbexception.h>
47 #include <cbplugin.h>
48 #include <cbproject.h>
49 #include <cbworkspace.h>
50 #include <ccmanager.h>
51 #include <configmanager.h>
52 #include <debuggermanager.h>
53 #include <editorcolourset.h>
54 #include <editormanager.h>
55 #include <filefilters.h>
56 #include <globals.h>
57 #include <logmanager.h>
58 #include <personalitymanager.h>
59 #include <pluginmanager.h>
60 #include <projectmanager.h>
61 #include <scriptingmanager.h>
62 #include <sdk_events.h>
63 #include <templatemanager.h>
64 #include <toolsmanager.h>
65 #include <uservarmanager.h>
66 
68 #include "debuggermenu.h"
69 
70 #include "cbcolourmanager.h"
71 #include "editorconfigurationdlg.h"
72 #include "projectmanagerui.h"
73 
75 {
76 public:
78  bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) override
79  {
80  if (!m_frame) return false;
81  return m_frame->OnDropFiles(x,y,filenames);
82  }
83 private:
85 };
86 
87 const static wxString gDefaultLayout = _T("Code::Blocks default");
88 static wxString gDefaultLayoutData; // this will keep the "hardcoded" default layout
89 static wxString gDefaultMessagePaneLayoutData; // this will keep default layout
90 
91 const static wxString gMinimalLayout = _T("Code::Blocks minimal");
92 static wxString gMinimalLayoutData; // this will keep the "hardcoded" default layout
93 static wxString gMinimalMessagePaneLayoutData; // this will keep default layout
94 
95 // In <wx/defs.h> wxID_FILE[X] exists only from 1..9,
96 // so create our own here with a *continuous* numbering!
97 // The wxID_FILE[X] enum usually starts at 5050 until 5059,
98 // followed by wxID_OK starting at 5100. (wxWidgets v2.6, v2.8 and v2.9)
99 // so we use the space in between starting from 5060
100 // and hoping it doesn't change too much in <wx/defs.h> ;-)
101 enum
102 {
103  wxID_CBFILE01 = 5060, // Recent files...
104  wxID_CBFILE02, // 5061
105  wxID_CBFILE03, // 5062
106  wxID_CBFILE04, // 5063
107  wxID_CBFILE05, // 5064
108  wxID_CBFILE06, // 5065
109  wxID_CBFILE07, // 5066
110  wxID_CBFILE08, // 5067
111  wxID_CBFILE09, // 5068
112  wxID_CBFILE10, // 5069
113  wxID_CBFILE11, // 5070
114  wxID_CBFILE12, // 5071
115  wxID_CBFILE13, // 5072
116  wxID_CBFILE14, // 5073
117  wxID_CBFILE15, // 5074
118  wxID_CBFILE16, // 5075
119  wxID_CBFILE17, // 5076 // Starting here for recent projects...
120  wxID_CBFILE18, // 5077
121  wxID_CBFILE19, // 5078
122  wxID_CBFILE20, // 5079
123  wxID_CBFILE21, // 5080
124  wxID_CBFILE22, // 5081
125  wxID_CBFILE23, // 5082
126  wxID_CBFILE24, // 5083
127  wxID_CBFILE25, // 5084
128  wxID_CBFILE26, // 5085
129  wxID_CBFILE27, // 5086
130  wxID_CBFILE28, // 5087
131  wxID_CBFILE29, // 5088
132  wxID_CBFILE30, // 5089
133  wxID_CBFILE31, // 5090
135 };
136 
137 int idToolNew = XRCID("idToolNew");
138 int idFileNew = XRCID("idFileNew");
139 int idFileNewEmpty = XRCID("idFileNewEmpty");
140 int idFileNewProject = XRCID("idFileNewProject");
141 int idFileNewTarget = XRCID("idFileNewTarget");
142 int idFileNewFile = XRCID("idFileNewFile");
143 int idFileNewCustom = XRCID("idFileNewCustom");
144 int idFileNewUser = XRCID("idFileNewUser");
145 int idFileOpen = XRCID("idFileOpen");
146 int idFileReopen = XRCID("idFileReopen");
147 int idFileOpenRecentFileClearHistory = XRCID("idFileOpenRecentFileClearHistory");
148 int idFileOpenRecentProjectClearHistory = XRCID("idFileOpenRecentProjectClearHistory");
149 int idFileImportProjectDevCpp = XRCID("idFileImportProjectDevCpp");
150 int idFileImportProjectMSVC = XRCID("idFileImportProjectMSVC");
151 int idFileImportProjectMSVCWksp = XRCID("idFileImportProjectMSVCWksp");
152 int idFileImportProjectMSVS = XRCID("idFileImportProjectMSVS");
153 int idFileImportProjectMSVSWksp = XRCID("idFileImportProjectMSVSWksp");
154 int idFileSave = XRCID("idFileSave");
155 int idFileSaveAs = XRCID("idFileSaveAs");
156 int idFileReopenProject = XRCID("idFileReopenProject");
157 int idFileSaveProject = XRCID("idFileSaveProject");
158 int idFileSaveProjectAs = XRCID("idFileSaveProjectAs");
159 int idFileSaveProjectTemplate = XRCID("idFileSaveProjectTemplate");
160 int idFileOpenDefWorkspace = XRCID("idFileOpenDefWorkspace");
161 int idFileSaveWorkspace = XRCID("idFileSaveWorkspace");
162 int idFileSaveWorkspaceAs = XRCID("idFileSaveWorkspaceAs");
163 int idFileSaveAll = XRCID("idFileSaveAll");
164 int idFileCloseWorkspace = XRCID("idFileCloseWorkspace");
165 int idFileClose = XRCID("idFileClose");
166 int idFileCloseAll = XRCID("idFileCloseAll");
167 int idFileCloseProject = XRCID("idFileCloseProject");
168 int idFilePrintSetup = XRCID("idFilePrintSetup");
169 int idFilePrint = XRCID("idFilePrint");
170 int idFileExit = XRCID("idFileExit");
171 
172 int idEditUndo = XRCID("idEditUndo");
173 int idEditRedo = XRCID("idEditRedo");
174 int idEditClearHistory = XRCID("idEditClearHistory");
175 int idEditCopy = XRCID("idEditCopy");
176 int idEditCut = XRCID("idEditCut");
177 int idEditPaste = XRCID("idEditPaste");
178 int idEditSwapHeaderSource = XRCID("idEditSwapHeaderSource");
179 int idEditGotoMatchingBrace = XRCID("idEditGotoMatchingBrace");
180 int idEditHighlightMode = XRCID("idEditHighlightMode");
181 int idEditHighlightModeText = XRCID("idEditHighlightModeText");
182 int idEditBookmarks = XRCID("idEditBookmarks");
183 int idEditBookmarksToggle = XRCID("idEditBookmarksToggle");
184 int idEditBookmarksPrevious = XRCID("idEditBookmarksPrevious");
185 int idEditBookmarksNext = XRCID("idEditBookmarksNext");
186 int idEditBookmarksClearAll = XRCID("idEditBookmarksClearAll");
187 int idEditFolding = XRCID("idEditFolding");
188 int idEditFoldAll = XRCID("idEditFoldAll");
189 int idEditUnfoldAll = XRCID("idEditUnfoldAll");
190 int idEditToggleAllFolds = XRCID("idEditToggleAllFolds");
191 int idEditFoldBlock = XRCID("idEditFoldBlock");
192 int idEditUnfoldBlock = XRCID("idEditUnfoldBlock");
193 int idEditToggleFoldBlock = XRCID("idEditToggleFoldBlock");
194 int idEditEOLMode = XRCID("idEditEOLMode");
195 int idEditEOLCRLF = XRCID("idEditEOLCRLF");
196 int idEditEOLCR = XRCID("idEditEOLCR");
197 int idEditEOLLF = XRCID("idEditEOLLF");
198 int idEditEncoding = XRCID("idEditEncoding");
199 int idEditEncodingDefault = XRCID("idEditEncodingDefault");
200 int idEditEncodingUseBom = XRCID("idEditEncodingUseBom");
201 int idEditEncodingAscii = XRCID("idEditEncodingAscii");
202 int idEditEncodingUtf7 = XRCID("idEditEncodingUtf7");
203 int idEditEncodingUtf8 = XRCID("idEditEncodingUtf8");
204 int idEditEncodingUnicode = XRCID("idEditEncodingUnicode");
205 int idEditEncodingUtf16 = XRCID("idEditEncodingUtf16");
206 int idEditEncodingUtf32 = XRCID("idEditEncodingUtf32");
207 int idEditEncodingUnicode16BE = XRCID("idEditEncodingUnicode16BE");
208 int idEditEncodingUnicode16LE = XRCID("idEditEncodingUnicode16LE");
209 int idEditEncodingUnicode32BE = XRCID("idEditEncodingUnicode32BE");
210 int idEditEncodingUnicode32LE = XRCID("idEditEncodingUnicode32LE");
211 int idEditSpecialCommands = XRCID("idEditSpecialCommands");
212 int idEditSpecialCommandsMovement = XRCID("idEditSpecialCommandsMovement");
213 int idEditParaUp = XRCID("idEditParaUp");
214 int idEditParaUpExtend = XRCID("idEditParaUpExtend");
215 int idEditParaDown = XRCID("idEditParaDown");
216 int idEditParaDownExtend = XRCID("idEditParaDownExtend");
217 int idEditWordPartLeft = XRCID("idEditWordPartLeft");
218 int idEditWordPartLeftExtend = XRCID("idEditWordPartLeftExtend");
219 int idEditWordPartRight = XRCID("idEditWordPartRight");
220 int idEditWordPartRightExtend = XRCID("idEditWordPartRightExtend");
221 int idEditSpecialCommandsZoom = XRCID("idEditSpecialCommandsZoom");
222 int idEditZoomIn = XRCID("idEditZoomIn");
223 int idEditZoomOut = XRCID("idEditZoomOut");
224 int idEditZoomReset = XRCID("idEditZoomReset");
225 int idEditSpecialCommandsLine = XRCID("idEditSpecialCommandsLine");
226 int idEditLineCut = XRCID("idEditLineCut");
227 int idEditLineDelete = XRCID("idEditLineDelete");
228 int idEditLineDuplicate = XRCID("idEditLineDuplicate");
229 int idEditLineTranspose = XRCID("idEditLineTranspose");
230 int idEditLineCopy = XRCID("idEditLineCopy");
231 int idEditLinePaste = XRCID("idEditLinePaste");
232 int idEditLineUp = XRCID("idEditLineUp");
233 int idEditLineDown = XRCID("idEditLineDown");
234 int idEditSpecialCommandsCase = XRCID("idEditSpecialCommandsCase");
235 int idEditUpperCase = XRCID("idEditUpperCase");
236 int idEditLowerCase = XRCID("idEditLowerCase");
237 int idEditSpecialCommandsOther = XRCID("idEditSpecialCommandsOther");
238 int idEditInsertNewLine = XRCID("idEditInsertNewLine");
239 int idEditGotoLineEnd = XRCID("idEditGotoLineEnd");
240 int idEditInsertNewLineBelow = XRCID("idEditInsertNewLineBelow");
241 int idEditInsertNewLineAbove = XRCID("idEditInsertNewLineAbove");
242 int idEditSelectAll = XRCID("idEditSelectAll");
243 int idEditSelectNext = XRCID("idEditSelectNext");
244 int idEditSelectNextSkip = XRCID("idEditSelectNextSkip");
245 int idEditCommentSelected = XRCID("idEditCommentSelected");
246 int idEditUncommentSelected = XRCID("idEditUncommentSelected");
247 int idEditToggleCommentSelected = XRCID("idEditToggleCommentSelected");
248 int idEditStreamCommentSelected = XRCID("idEditStreamCommentSelected");
249 int idEditBoxCommentSelected = XRCID("idEditBoxCommentSelected");
250 int idEditShowCallTip = XRCID("idEditShowCallTip");
252 
253 int idViewLayoutDelete = XRCID("idViewLayoutDelete");
254 int idViewLayoutSave = XRCID("idViewLayoutSave");
255 int idViewToolbars = XRCID("idViewToolbars");
256 int idViewToolFit = XRCID("idViewToolFit");
257 int idViewToolOptimize = XRCID("idViewToolOptimize");
258 int idViewToolMain = XRCID("idViewToolMain");
259 int idViewToolDebugger = XRCID("idViewToolDebugger");
260 int idViewManager = XRCID("idViewManager");
261 int idViewLogManager = XRCID("idViewLogManager");
262 int idViewStartPage = XRCID("idViewStartPage");
263 int idViewStatusbar = XRCID("idViewStatusbar");
264 int idViewScriptConsole = XRCID("idViewScriptConsole");
265 int idViewHideEditorTabs = XRCID("idViewHideEditorTabs");
266 int idViewFocusEditor = XRCID("idViewFocusEditor");
267 int idViewFocusManagement = XRCID("idViewFocusManagement");
268 int idViewFocusLogsAndOthers = XRCID("idViewFocusLogsAndOthers");
269 int idViewSwitchTabs = XRCID("idViewSwitchTabs");
270 int idViewFullScreen = XRCID("idViewFullScreen");
271 
272 int idSearchFind = XRCID("idSearchFind");
273 int idSearchFindInFiles = XRCID("idSearchFindInFiles");
274 int idSearchFindNext = XRCID("idSearchFindNext");
275 int idSearchFindPrevious = XRCID("idSearchFindPrevious");
276 int idSearchFindSelectedNext = XRCID("idSearchFindSelectedNext");
277 int idSearchFindSelectedPrevious = XRCID("idSearchFindSelectedPrevious");
278 int idSearchReplace = XRCID("idSearchReplace");
279 int idSearchReplaceInFiles = XRCID("idSearchReplaceInFiles");
280 int idSearchGotoLine = XRCID("idSearchGotoLine");
281 int idSearchGotoNextChanged = XRCID("idSearchGotoNextChanged");
282 int idSearchGotoPreviousChanged = XRCID("idSearchGotoPreviousChanged");
283 
284 int idSettingsEnvironment = XRCID("idSettingsEnvironment");
285 int idSettingsGlobalUserVars = XRCID("idSettingsGlobalUserVars");
286 int idSettingsEditor = XRCID("idSettingsEditor");
287 int idSettingsCompiler = XRCID("idSettingsCompiler");
288 int idSettingsDebugger = XRCID("idSettingsDebugger");
289 int idPluginsManagePlugins = XRCID("idPluginsManagePlugins");
290 int idSettingsScripting = XRCID("idSettingsScripting");
291 
292 int idHelpTips = XRCID("idHelpTips");
293 int idHelpPlugins = XRCID("idHelpPlugins");
294 
295 int idLeftSash = XRCID("idLeftSash");
296 int idBottomSash = XRCID("idBottomSash");
297 int idCloseFullScreen = XRCID("idCloseFullScreen");
298 
305 
306 BEGIN_EVENT_TABLE(MainFrame, wxFrame)
307  EVT_ERASE_BACKGROUND(MainFrame::OnEraseBackground)
308  EVT_SIZE(MainFrame::OnSize)
310 
311  EVT_UPDATE_UI(idFileOpen, MainFrame::OnFileMenuUpdateUI)
312  EVT_UPDATE_UI(idFileOpenRecentFileClearHistory, MainFrame::OnFileMenuUpdateUI)
313  EVT_UPDATE_UI(idFileOpenRecentProjectClearHistory, MainFrame::OnFileMenuUpdateUI)
314  EVT_UPDATE_UI(idFileSave, MainFrame::OnFileMenuUpdateUI)
315  EVT_UPDATE_UI(idFileSaveAs, MainFrame::OnFileMenuUpdateUI)
316  EVT_UPDATE_UI(idFileOpenDefWorkspace, MainFrame::OnFileMenuUpdateUI)
317  EVT_UPDATE_UI(idFileSaveWorkspace, MainFrame::OnFileMenuUpdateUI)
318  EVT_UPDATE_UI(idFileSaveWorkspaceAs, MainFrame::OnFileMenuUpdateUI)
319  EVT_UPDATE_UI(idFileCloseWorkspace, MainFrame::OnFileMenuUpdateUI)
320  EVT_UPDATE_UI(idFileClose, MainFrame::OnFileMenuUpdateUI)
321  EVT_UPDATE_UI(idFileCloseAll, MainFrame::OnFileMenuUpdateUI)
322  EVT_UPDATE_UI(idFilePrintSetup, MainFrame::OnFileMenuUpdateUI)
323  EVT_UPDATE_UI(idFilePrint, MainFrame::OnFileMenuUpdateUI)
324 
325  EVT_UPDATE_UI(idFileReopenProject, MainFrame::OnFileMenuUpdateUI)
326  EVT_UPDATE_UI(idFileSaveProject, MainFrame::OnFileMenuUpdateUI)
327  EVT_UPDATE_UI(idFileSaveProjectAs, MainFrame::OnFileMenuUpdateUI)
328  EVT_UPDATE_UI(idFileSaveProjectTemplate, MainFrame::OnFileMenuUpdateUI)
329  EVT_UPDATE_UI(idFileSaveAll, MainFrame::OnFileMenuUpdateUI)
330  EVT_UPDATE_UI(idFileCloseProject, MainFrame::OnFileMenuUpdateUI)
331 
332  EVT_UPDATE_UI(idEditUndo, MainFrame::OnEditMenuUpdateUI)
333  EVT_UPDATE_UI(idEditRedo, MainFrame::OnEditMenuUpdateUI)
334  EVT_UPDATE_UI(idEditClearHistory, MainFrame::OnEditMenuUpdateUI)
335  EVT_UPDATE_UI(idEditCopy, MainFrame::OnEditMenuUpdateUI)
336  EVT_UPDATE_UI(idEditCut, MainFrame::OnEditMenuUpdateUI)
337  EVT_UPDATE_UI(idEditPaste, MainFrame::OnEditMenuUpdateUI)
338  EVT_UPDATE_UI(idEditSwapHeaderSource, MainFrame::OnEditMenuUpdateUI)
339  EVT_UPDATE_UI(idEditGotoMatchingBrace, MainFrame::OnEditMenuUpdateUI)
340  EVT_UPDATE_UI(idEditFoldAll, MainFrame::OnEditMenuUpdateUI)
341  EVT_UPDATE_UI(idEditUnfoldAll, MainFrame::OnEditMenuUpdateUI)
342  EVT_UPDATE_UI(idEditToggleAllFolds, MainFrame::OnEditMenuUpdateUI)
343  EVT_UPDATE_UI(idEditFoldBlock, MainFrame::OnEditMenuUpdateUI)
344  EVT_UPDATE_UI(idEditUnfoldBlock, MainFrame::OnEditMenuUpdateUI)
345  EVT_UPDATE_UI(idEditToggleFoldBlock, MainFrame::OnEditMenuUpdateUI)
346  EVT_UPDATE_UI(idEditEOLCRLF, MainFrame::OnEditMenuUpdateUI)
347  EVT_UPDATE_UI(idEditEOLCR, MainFrame::OnEditMenuUpdateUI)
348  EVT_UPDATE_UI(idEditEOLLF, MainFrame::OnEditMenuUpdateUI)
349  EVT_UPDATE_UI(idEditEncoding, MainFrame::OnEditMenuUpdateUI)
350  EVT_UPDATE_UI(idEditSelectAll, MainFrame::OnEditMenuUpdateUI)
351  EVT_UPDATE_UI(idEditSelectNext, MainFrame::OnEditMenuUpdateUI)
352  EVT_UPDATE_UI(idEditSelectNextSkip, MainFrame::OnEditMenuUpdateUI)
353  EVT_UPDATE_UI(idEditBookmarksToggle, MainFrame::OnEditMenuUpdateUI)
354  EVT_UPDATE_UI(idEditBookmarksNext, MainFrame::OnEditMenuUpdateUI)
355  EVT_UPDATE_UI(idEditBookmarksPrevious, MainFrame::OnEditMenuUpdateUI)
356  EVT_UPDATE_UI(idEditBookmarksClearAll, MainFrame::OnEditMenuUpdateUI)
357  EVT_UPDATE_UI(idEditCommentSelected, MainFrame::OnEditMenuUpdateUI)
358  EVT_UPDATE_UI(idEditUncommentSelected, MainFrame::OnEditMenuUpdateUI)
359  EVT_UPDATE_UI(idEditToggleCommentSelected, MainFrame::OnEditMenuUpdateUI)
360  EVT_UPDATE_UI(idEditStreamCommentSelected, MainFrame::OnEditMenuUpdateUI)
361  EVT_UPDATE_UI(idEditBoxCommentSelected, MainFrame::OnEditMenuUpdateUI)
362  EVT_UPDATE_UI(idEditShowCallTip, MainFrame::OnEditMenuUpdateUI)
363  EVT_UPDATE_UI(idEditCompleteCode, MainFrame::OnEditMenuUpdateUI)
364 
365  EVT_UPDATE_UI(idSearchFind, MainFrame::OnSearchMenuUpdateUI)
366  EVT_UPDATE_UI(idSearchFindInFiles, MainFrame::OnSearchMenuUpdateUI)
367  EVT_UPDATE_UI(idSearchFindNext, MainFrame::OnSearchMenuUpdateUI)
368  EVT_UPDATE_UI(idSearchFindPrevious, MainFrame::OnSearchMenuUpdateUI)
369  EVT_UPDATE_UI(idSearchFindSelectedNext, MainFrame::OnSearchMenuUpdateUI)
370  EVT_UPDATE_UI(idSearchFindSelectedPrevious, MainFrame::OnSearchMenuUpdateUI)
371  EVT_UPDATE_UI(idSearchReplace, MainFrame::OnSearchMenuUpdateUI)
372  EVT_UPDATE_UI(idSearchReplaceInFiles, MainFrame::OnSearchMenuUpdateUI)
373  EVT_UPDATE_UI(idSearchGotoLine, MainFrame::OnSearchMenuUpdateUI)
374  EVT_UPDATE_UI(idSearchGotoNextChanged, MainFrame::OnSearchMenuUpdateUI)
375  EVT_UPDATE_UI(idSearchGotoPreviousChanged, MainFrame::OnSearchMenuUpdateUI)
376 
377  EVT_UPDATE_UI(idViewToolMain, MainFrame::OnViewMenuUpdateUI)
378  EVT_UPDATE_UI(idViewLogManager, MainFrame::OnViewMenuUpdateUI)
379  EVT_UPDATE_UI(idViewStartPage, MainFrame::OnViewMenuUpdateUI)
380  EVT_UPDATE_UI(idViewManager, MainFrame::OnViewMenuUpdateUI)
381  EVT_UPDATE_UI(idViewStatusbar, MainFrame::OnViewMenuUpdateUI)
382  EVT_UPDATE_UI(idViewScriptConsole, MainFrame::OnViewMenuUpdateUI)
383  EVT_UPDATE_UI(idViewHideEditorTabs, MainFrame::OnViewMenuUpdateUI)
384  EVT_UPDATE_UI(idViewFocusEditor, MainFrame::OnViewMenuUpdateUI)
385  EVT_UPDATE_UI(idViewFocusManagement, MainFrame::OnViewMenuUpdateUI)
386  EVT_UPDATE_UI(idViewFocusLogsAndOthers, MainFrame::OnViewMenuUpdateUI)
387  EVT_UPDATE_UI(idViewFullScreen, MainFrame::OnViewMenuUpdateUI)
388 
389  EVT_MENU(idFileNewEmpty, MainFrame::OnFileNewWhat)
390  EVT_MENU(idFileNewProject, MainFrame::OnFileNewWhat)
391  EVT_MENU(idFileNewTarget, MainFrame::OnFileNewWhat)
392  EVT_MENU(idFileNewFile, MainFrame::OnFileNewWhat)
393  EVT_MENU(idFileNewCustom, MainFrame::OnFileNewWhat)
394  EVT_MENU(idFileNewUser, MainFrame::OnFileNewWhat)
395 
396  EVT_MENU(idToolNew, MainFrame::OnFileNew)
397  EVT_MENU(idFileOpen, MainFrame::OnFileOpen)
398  EVT_MENU(idFileOpenRecentProjectClearHistory, MainFrame::OnFileOpenRecentProjectClearHistory)
399  EVT_MENU(idFileOpenRecentFileClearHistory, MainFrame::OnFileOpenRecentClearHistory)
402  EVT_MENU(idFileImportProjectDevCpp, MainFrame::OnFileImportProjectDevCpp)
403  EVT_MENU(idFileImportProjectMSVC, MainFrame::OnFileImportProjectMSVC)
404  EVT_MENU(idFileImportProjectMSVCWksp, MainFrame::OnFileImportProjectMSVCWksp)
405  EVT_MENU(idFileImportProjectMSVS, MainFrame::OnFileImportProjectMSVS)
406  EVT_MENU(idFileImportProjectMSVSWksp, MainFrame::OnFileImportProjectMSVSWksp)
407  EVT_MENU(idFileSave, MainFrame::OnFileSave)
408  EVT_MENU(idFileSaveAs, MainFrame::OnFileSaveAs)
409  EVT_MENU(idFileSaveProject, MainFrame::OnFileSaveProject)
410  EVT_MENU(idFileSaveProjectAs, MainFrame::OnFileSaveProjectAs)
411  EVT_MENU(idFileSaveProjectTemplate, MainFrame::OnFileSaveProjectTemplate)
412  EVT_MENU(idFileOpenDefWorkspace, MainFrame::OnFileOpenDefWorkspace)
413  EVT_MENU(idFileSaveWorkspace, MainFrame::OnFileSaveWorkspace)
414  EVT_MENU(idFileSaveWorkspaceAs, MainFrame::OnFileSaveWorkspaceAs)
415  EVT_MENU(idFileSaveAll, MainFrame::OnFileSaveAll)
416  EVT_MENU(idFileCloseWorkspace, MainFrame::OnFileCloseWorkspace)
417  EVT_MENU(idFileClose, MainFrame::OnFileClose)
418  EVT_MENU(idFileCloseAll, MainFrame::OnFileCloseAll)
419  EVT_MENU(idFileCloseProject, MainFrame::OnFileCloseProject)
420  EVT_MENU(idFilePrint, MainFrame::OnFilePrint)
421  EVT_MENU(idFileExit, MainFrame::OnFileQuit)
422  EVT_MENU(idFileNext, MainFrame::OnFileNext)
423  EVT_MENU(idFilePrev, MainFrame::OnFilePrev)
424 
425  EVT_MENU(idEditUndo, MainFrame::OnEditUndo)
426  EVT_MENU(idEditRedo, MainFrame::OnEditRedo)
427  EVT_MENU(idEditClearHistory, MainFrame::OnEditClearHistory)
428  EVT_MENU(idEditCopy, MainFrame::OnEditCopy)
429  EVT_MENU(idEditCut, MainFrame::OnEditCut)
430  EVT_MENU(idEditPaste, MainFrame::OnEditPaste)
431  EVT_MENU(idEditSwapHeaderSource, MainFrame::OnEditSwapHeaderSource)
432  EVT_MENU(idEditGotoMatchingBrace, MainFrame::OnEditGotoMatchingBrace)
433  EVT_MENU(idEditHighlightModeText, MainFrame::OnEditHighlightMode)
434  EVT_MENU(idEditFoldAll, MainFrame::OnEditFoldAll)
435  EVT_MENU(idEditUnfoldAll, MainFrame::OnEditUnfoldAll)
436  EVT_MENU(idEditToggleAllFolds, MainFrame::OnEditToggleAllFolds)
437  EVT_MENU(idEditFoldBlock, MainFrame::OnEditFoldBlock)
438  EVT_MENU(idEditUnfoldBlock, MainFrame::OnEditUnfoldBlock)
439  EVT_MENU(idEditToggleFoldBlock, MainFrame::OnEditToggleFoldBlock)
440  EVT_MENU(idEditEOLCRLF, MainFrame::OnEditEOLMode)
441  EVT_MENU(idEditEOLCR, MainFrame::OnEditEOLMode)
442  EVT_MENU(idEditEOLLF, MainFrame::OnEditEOLMode)
443  EVT_MENU(idEditEncodingDefault, MainFrame::OnEditEncoding)
444  EVT_MENU(idEditEncodingUseBom, MainFrame::OnEditEncoding)
445  EVT_MENU(idEditEncodingAscii, MainFrame::OnEditEncoding)
446  EVT_MENU(idEditEncodingUtf7, MainFrame::OnEditEncoding)
447  EVT_MENU(idEditEncodingUtf8, MainFrame::OnEditEncoding)
448  EVT_MENU(idEditEncodingUnicode, MainFrame::OnEditEncoding)
449  EVT_MENU(idEditEncodingUtf16, MainFrame::OnEditEncoding)
450  EVT_MENU(idEditEncodingUtf32, MainFrame::OnEditEncoding)
451  EVT_MENU(idEditEncodingUnicode16BE, MainFrame::OnEditEncoding)
452  EVT_MENU(idEditEncodingUnicode16LE, MainFrame::OnEditEncoding)
453  EVT_MENU(idEditEncodingUnicode32BE, MainFrame::OnEditEncoding)
454  EVT_MENU(idEditEncodingUnicode32LE, MainFrame::OnEditEncoding)
455  EVT_MENU(idEditParaUp, MainFrame::OnEditParaUp)
456  EVT_MENU(idEditParaUpExtend, MainFrame::OnEditParaUpExtend)
457  EVT_MENU(idEditParaDown, MainFrame::OnEditParaDown)
458  EVT_MENU(idEditParaDownExtend, MainFrame::OnEditParaDownExtend)
459  EVT_MENU(idEditWordPartLeft, MainFrame::OnEditWordPartLeft)
460  EVT_MENU(idEditWordPartLeftExtend, MainFrame::OnEditWordPartLeftExtend)
461  EVT_MENU(idEditWordPartRight, MainFrame::OnEditWordPartRight)
462  EVT_MENU(idEditWordPartRightExtend, MainFrame::OnEditWordPartRightExtend)
463  EVT_MENU(idEditZoomIn, MainFrame::OnEditZoomIn)
464  EVT_MENU(idEditZoomOut, MainFrame::OnEditZoomOut)
465  EVT_MENU(idEditZoomReset, MainFrame::OnEditZoomReset)
466  EVT_MENU(idEditLineCut, MainFrame::OnEditLineCut)
467  EVT_MENU(idEditLineDelete, MainFrame::OnEditLineDelete)
468  EVT_MENU(idEditLineDuplicate, MainFrame::OnEditLineDuplicate)
469  EVT_MENU(idEditLineTranspose, MainFrame::OnEditLineTranspose)
470  EVT_MENU(idEditLineCopy, MainFrame::OnEditLineCopy)
471  EVT_MENU(idEditLinePaste, MainFrame::OnEditLinePaste)
472  EVT_MENU(idEditLineUp, MainFrame::OnEditLineMove)
473  EVT_MENU(idEditLineDown, MainFrame::OnEditLineMove)
474  EVT_MENU(idEditUpperCase, MainFrame::OnEditUpperCase)
475  EVT_MENU(idEditLowerCase, MainFrame::OnEditLowerCase)
476  EVT_MENU(idEditInsertNewLine, MainFrame::OnEditInsertNewLine)
477  EVT_MENU(idEditGotoLineEnd, MainFrame::OnEditGotoLineEnd)
478  EVT_MENU(idEditInsertNewLineBelow, MainFrame::OnEditInsertNewLineBelow)
479  EVT_MENU(idEditInsertNewLineAbove, MainFrame::OnEditInsertNewLineAbove)
480  EVT_MENU(idEditSelectAll, MainFrame::OnEditSelectAll)
481  EVT_MENU(idEditSelectNext, MainFrame::OnEditSelectNext)
482  EVT_MENU(idEditSelectNextSkip, MainFrame::OnEditSelectNextSkip)
483  EVT_MENU(idEditBookmarksToggle, MainFrame::OnEditBookmarksToggle)
484  EVT_MENU(idEditBookmarksNext, MainFrame::OnEditBookmarksNext)
485  EVT_MENU(idEditBookmarksPrevious, MainFrame::OnEditBookmarksPrevious)
486  EVT_MENU(idEditBookmarksClearAll, MainFrame::OnEditBookmarksClearAll)
487  EVT_MENU(idEditCommentSelected, MainFrame::OnEditCommentSelected)
488  EVT_MENU(idEditUncommentSelected, MainFrame::OnEditUncommentSelected)
489  EVT_MENU(idEditToggleCommentSelected, MainFrame::OnEditToggleCommentSelected)
490  EVT_MENU(idEditStreamCommentSelected, MainFrame::OnEditStreamCommentSelected)
491  EVT_MENU(idEditBoxCommentSelected, MainFrame::OnEditBoxCommentSelected)
492  EVT_MENU(idEditShowCallTip, MainFrame::OnEditShowCallTip)
493  EVT_MENU(idEditCompleteCode, MainFrame::OnEditCompleteCode)
494 
495  EVT_MENU(idSearchFind, MainFrame::OnSearchFind)
496  EVT_MENU(idSearchFindInFiles, MainFrame::OnSearchFind)
497  EVT_MENU(idSearchFindNext, MainFrame::OnSearchFindNext)
498  EVT_MENU(idSearchFindPrevious, MainFrame::OnSearchFindNext)
499  EVT_MENU(idSearchFindSelectedNext, MainFrame::OnSearchFindNextSelected)
500  EVT_MENU(idSearchFindSelectedPrevious, MainFrame::OnSearchFindNextSelected)
501  EVT_MENU(idSearchReplace, MainFrame::OnSearchReplace)
502  EVT_MENU(idSearchReplaceInFiles, MainFrame::OnSearchReplace)
503  EVT_MENU(idSearchGotoLine, MainFrame::OnSearchGotoLine)
504  EVT_MENU(idSearchGotoNextChanged, MainFrame::OnSearchGotoNextChanged)
505  EVT_MENU(idSearchGotoPreviousChanged, MainFrame::OnSearchGotoPrevChanged)
506 
507  EVT_MENU(idViewLayoutSave, MainFrame::OnViewLayoutSave)
508  EVT_MENU(idViewLayoutDelete, MainFrame::OnViewLayoutDelete)
509  EVT_MENU(idViewToolFit, MainFrame::OnViewToolbarsFit)
510  EVT_MENU(idViewToolOptimize, MainFrame::OnViewToolbarsOptimize)
511  EVT_MENU(idViewToolMain, MainFrame::OnToggleBar)
512  EVT_MENU(idViewToolDebugger, MainFrame::OnToggleBar)
513  EVT_MENU(idViewLogManager, MainFrame::OnToggleBar)
514  EVT_MENU(idViewManager, MainFrame::OnToggleBar)
515  EVT_MENU(idViewStatusbar, MainFrame::OnToggleStatusBar)
516  EVT_MENU(idViewScriptConsole, MainFrame::OnViewScriptConsole)
517  EVT_MENU(idViewHideEditorTabs, MainFrame::OnViewHideEditorTabs)
518  EVT_MENU(idViewFocusEditor, MainFrame::OnFocusEditor)
519  EVT_MENU(idViewFocusManagement, MainFrame::OnFocusManagement)
520  EVT_MENU(idViewFocusLogsAndOthers, MainFrame::OnFocusLogsAndOthers)
521  EVT_MENU(idViewSwitchTabs, MainFrame::OnSwitchTabs)
522  EVT_MENU(idViewFullScreen, MainFrame::OnToggleFullScreen)
523  EVT_MENU(idViewStartPage, MainFrame::OnToggleStartPage)
524 
525  EVT_MENU(idSettingsEnvironment, MainFrame::OnSettingsEnvironment)
526  EVT_MENU(idSettingsGlobalUserVars, MainFrame::OnGlobalUserVars)
527  EVT_MENU(idSettingsEditor, MainFrame::OnSettingsEditor)
528  EVT_MENU(idSettingsCompiler, MainFrame::OnSettingsCompiler)
529  EVT_MENU(idSettingsDebugger, MainFrame::OnSettingsDebugger)
530  EVT_MENU(idPluginsManagePlugins, MainFrame::OnSettingsPlugins)
531  EVT_MENU(idSettingsScripting, MainFrame::OnSettingsScripting)
532 
533  EVT_MENU(wxID_ABOUT, MainFrame::OnHelpAbout)
534  EVT_MENU(idHelpTips, MainFrame::OnHelpTips)
535 
536  EVT_MENU(idStartHerePageLink, MainFrame::OnStartHereLink)
537 
539  EVT_NOTEBOOK_PAGE_CHANGED(ID_NBEditorManager, MainFrame::OnPageChanged)
540 
541  // Highlightbutton
542  EVT_BUTTON(idHighlightButton, MainFrame::OnHighlightMenu)
544  EVT_BUTTON(idCloseFullScreen, MainFrame::OnToggleFullScreen)
545 
546 
547  EVT_MENU(idShiftTab, MainFrame::OnShiftTab)
548  EVT_MENU(idCtrlAltTab, MainFrame::OnCtrlAltTab)
549 
550 
551  EVT_RIGHT_UP(MainFrame::OnMouseRightUp)
552 
553 END_EVENT_TABLE()
554 
556  : wxFrame(parent, -1, _T("MainWin"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE),
557  m_LayoutManager(this),
558  m_pAccel(nullptr),
559  m_filesHistory(_("&File"), wxT("/recent_files"), idFileOpenRecentFileClearHistory, wxID_CBFILE01),
560  m_projectsHistory(_("&File"), wxT("/recent_projects"), idFileOpenRecentProjectClearHistory, wxID_CBFILE17),
561  m_pCloseFullScreenBtn(nullptr),
562  m_pEdMan(nullptr),
563  m_pPrjMan(nullptr),
564  m_pPrjManUI(nullptr),
565  m_pLogMan(nullptr),
566  m_pInfoPane(nullptr),
567  m_pToolbar(nullptr),
568  m_ToolsMenu(nullptr),
569  m_HelpPluginsMenu(nullptr),
570  m_ScanningForPlugins(false),
571  m_StartupDone(false), // one-time flag
572  m_InitiatedShutdown(false),
573  m_AutoHideLockCounter(0),
574  m_LastCtrlAltTabWindow(0),
575  m_LastLayoutIsTemp(false),
576  m_pScriptConsole(nullptr),
577  m_pBatchBuildDialog(nullptr),
578  // Highlightbutton
579  m_pHighlightButton(nullptr)
580 {
581  Manager::Get(this); // provide manager with handle to MainFrame (this)
582 
583  // register event sinks
584  RegisterEvents();
585 
586  // New: Allow drag and drop of files into the editor
587  SetDropTarget(new cbFileDropTarget(this));
588 
589  // Accelerator table
590  wxAcceleratorEntry entries[8];
591  entries[0].Set(wxACCEL_CTRL | wxACCEL_SHIFT, (int) 'W', idFileCloseAll);
592  entries[1].Set(wxACCEL_CTRL | wxACCEL_SHIFT, WXK_F4, idFileCloseAll);
593  entries[2].Set(wxACCEL_CTRL, (int) 'W', idFileClose);
594  entries[3].Set(wxACCEL_CTRL, WXK_F4, idFileClose);
595  entries[4].Set(wxACCEL_CTRL, WXK_F6, idFileNext);
596  entries[5].Set(wxACCEL_CTRL | wxACCEL_SHIFT, WXK_F6, idFilePrev);
597  entries[6].Set(wxACCEL_SHIFT, WXK_TAB, idShiftTab);
598  entries[7].Set(wxACCEL_CTRL | wxACCEL_ALT, WXK_TAB, idCtrlAltTab);
599  m_pAccel = new wxAcceleratorTable(8, entries);
600 
601  SetAcceleratorTable(*m_pAccel);
602 
603  // add file filters for supported projects/workspaces
605 
606  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
607  m_SmallToolBar = cfg->ReadBool(_T("/environment/toolbar_size"), true);
608  CreateIDE();
609 
610 #ifdef __WXMSW__
611  SetIcon(wxICON(A_MAIN_ICON));
612 #else
613  SetIcon(wxIcon(app));
614 #endif // __WXMSW__
615 
616  // 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:
617  DoCreateStatusBar();
618  SetStatusText(_("Welcome to ")+ appglobals::AppName + _T("!"));
619 
620  wxStatusBar *sb = GetStatusBar();
621  if (sb)
622  sb->Show(cfg->ReadBool(_T("/main_frame/statusbar"), true));
623 
624  SetTitle(appglobals::AppName + _T(" v") + appglobals::AppVersion);
625 
626  LoadWindowSize();
627  ScanForPlugins();
628  CreateToolbars();
629 
631 
632  // save default view
633  wxString deflayout = cfg->Read(_T("/main_frame/layout/default"));
634  if (deflayout.IsEmpty())
635  cfg->Write(_T("/main_frame/layout/default"), gDefaultLayout);
636  DoFixToolbarsLayout();
637  gDefaultLayoutData = m_LayoutManager.SavePerspective(); // keep the "hardcoded" layout handy
638  gDefaultMessagePaneLayoutData = m_pInfoPane->SaveTabOrder();
639  SaveViewLayout(gDefaultLayout, gDefaultLayoutData, gDefaultMessagePaneLayoutData);
640 
641  // generate default minimal layout
642  wxAuiPaneInfoArray& panes = m_LayoutManager.GetAllPanes();
643  for (size_t i = 0; i < panes.GetCount(); ++i)
644  {
645  wxAuiPaneInfo& info = panes[i];
646  if (!(info.name == _T("MainPane")))
647  info.Hide();
648  }
649  gMinimalLayoutData = m_LayoutManager.SavePerspective(); // keep the "hardcoded" layout handy
650  gMinimalMessagePaneLayoutData = m_pInfoPane->SaveTabOrder();
651  SaveViewLayout(gMinimalLayout, gMinimalLayoutData, gMinimalMessagePaneLayoutData);
652 
653  LoadWindowState();
654 
655  ShowHideStartPage();
656 
657  RegisterScriptFunctions();
658  RunStartupScripts();
659 
660  Manager::Get()->GetLogManager()->DebugLog(_T("Initializing plugins..."));
661 }
662 
664 {
665  SetAcceleratorTable(wxNullAcceleratorTable);
666  delete m_pAccel;
667 
668  DeInitPrinting();
669 
670  delete m_debuggerMenuHandler;
671  delete m_debuggerToolbarHandler;
672 }
673 
675 {
676  Manager* m = Manager::Get();
677 
679 
688 
694 
699 
703 
713 }
714 
715 void MainFrame::ShowTips(bool forceShow)
716 {
717  bool showAtStartup = Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/show_tips"), false);
718  if (forceShow || showAtStartup)
719  {
720  wxString tipsFile = ConfigManager::GetDataFolder() + _T("/tips.txt");
721  long tipsIndex = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/next_tip"), 0);
722  wxTipProvider* tipProvider = wxCreateFileTipProvider(tipsFile, tipsIndex);
723  showAtStartup = wxShowTip(this, tipProvider, showAtStartup);
724  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/show_tips"), showAtStartup);
725  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/next_tip"), (int)tipProvider->GetCurrentTip());
726  delete tipProvider;
727  }
728 }
729 
731 {
732  int leftW = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left_block_width"), 200);
733  wxSize clientsize = GetClientSize();
734 
735  // Create CloseFullScreen Button, and hide it initially
736  m_pCloseFullScreenBtn = new wxButton(this, idCloseFullScreen, _( "Close full screen" ), wxDefaultPosition );
737  m_pCloseFullScreenBtn->Show( false );
738 
739  // management panel
740  m_pPrjMan = Manager::Get()->GetProjectManager();
741  if (!Manager::IsBatchBuild())
742  {
743  m_pPrjManUI = new ProjectManagerUI;
744  m_LayoutManager.AddPane( m_pPrjManUI->GetNotebook(),
745  wxAuiPaneInfo().Name(wxT("ManagementPane")).Caption(_("Management")).
746  BestSize(wxSize(leftW, clientsize.GetHeight())).
747  MinSize(wxSize(100,100)).Left().Layer(1) );
748  }
749  else
750  m_pPrjManUI = new BatchProjectManagerUI;
751  m_pPrjMan->SetUI(m_pPrjManUI);
752 
753  // logs manager
754  SetupGUILogging();
755  SetupDebuggerUI();
756 
757  CreateMenubar();
758 
759  m_pEdMan = Manager::Get()->GetEditorManager();
760  m_pLogMan = Manager::Get()->GetLogManager();
761 
762  // editor manager
763  m_LayoutManager.AddPane(m_pEdMan->GetNotebook(), wxAuiPaneInfo().Name(wxT("MainPane")).
764  CentrePane());
765 
766  // script console
767  m_pScriptConsole = new ScriptConsole(this, -1);
768  m_LayoutManager.AddPane(m_pScriptConsole, wxAuiPaneInfo().Name(wxT("ScriptConsole")).
769  Caption(_("Scripting console")).Float().MinSize(100,100).FloatingPosition(300, 200).Hide());
770 
771  DoUpdateLayout();
772  DoUpdateLayoutColours();
773  DoUpdateEditorStyle();
774 
775  m_pEdMan->GetNotebook()->SetDropTarget(new cbFileDropTarget(this));
776  if (m_pPrjManUI->GetNotebook())
777  m_pPrjManUI->GetNotebook()->SetDropTarget(new cbFileDropTarget(this));
778 
780 }
781 
782 
784 {
785  // 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"
786  m_LayoutManager.SetDockSizeConstraint(0.75,0.75);
787 
788  int bottomH = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/bottom_block_height"), 150);
789  wxSize clientsize = GetClientSize();
790 
792 
793  if (!Manager::IsBatchBuild())
794  {
795  m_pInfoPane = new InfoPane(this);
796  m_LayoutManager.AddPane(m_pInfoPane, wxAuiPaneInfo().
797  Name(wxT("MessagesPane")).Caption(_("Logs & others")).
798  BestSize(wxSize(clientsize.GetWidth(), bottomH)).//MinSize(wxSize(50,50)).
799  Bottom());
800 
801  wxWindow* log;
802 
803  for (size_t i = LogManager::app_log; i < LogManager::max_logs; ++i)
804  {
805  if ((log = mgr->Slot(i).GetLogger()->CreateControl(m_pInfoPane)))
806  m_pInfoPane->AddLogger(mgr->Slot(i).GetLogger(), log, mgr->Slot(i).title, mgr->Slot(i).icon);
807  }
808 
809  m_findReplace.CreateSearchLog();
810  }
811  else
812  {
813  m_pBatchBuildDialog = new BatchLogWindow(this, _("Code::Blocks - Batch build"));
814  wxSizer* s = new wxBoxSizer(wxVERTICAL);
815  m_pInfoPane = new InfoPane(m_pBatchBuildDialog);
816  s->Add(m_pInfoPane, 1, wxEXPAND);
817  m_pBatchBuildDialog->SetSizer(s);
818 
819  // setting &g_null_log causes the app to crash on exit for some reason...
822  }
823 
824  mgr->NotifyUpdate();
825  m_pInfoPane->SetDropTarget(new cbFileDropTarget(this));
826 }
827 
829 {
830  m_debuggerMenuHandler = new DebuggerMenuHandler;
831  m_debuggerToolbarHandler = new DebuggerToolbarHandler(m_debuggerMenuHandler);
832  m_debuggerMenuHandler->SetEvtHandlerEnabled(false);
833  m_debuggerToolbarHandler->SetEvtHandlerEnabled(false);
834  wxWindow* window = Manager::Get()->GetAppWindow();
835  if (window)
836  {
837  window->PushEventHandler(m_debuggerMenuHandler);
838  window->PushEventHandler(m_debuggerToolbarHandler);
839  }
840  m_debuggerMenuHandler->SetEvtHandlerEnabled(true);
841  m_debuggerToolbarHandler->SetEvtHandlerEnabled(true);
842 
843  if (!Manager::IsBatchBuild())
844  {
846  m_debuggerMenuHandler->RegisterDefaultWindowItems();
847  }
848 }
849 
851 
853 {
854  SqPlus::SQClassDef<MainFrame>("MainFrame").
855  func(&MainFrame::Open, "Open");
856 
857  SqPlus::BindVariable(this, "App", SqPlus::VAR_ACCESS_READ_ONLY);
858 }
859 
861 {
862  ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("scripting"));
863  wxArrayString keys = mgr->EnumerateKeys(_T("/startup_scripts"));
864 
865  for (size_t i = 0; i < keys.GetCount(); ++i)
866  {
867  ScriptEntry se;
868  wxString ser;
869  if (mgr->Read(_T("/startup_scripts/") + keys[i], &ser))
870  {
871  se.SerializeIn(ser);
872  if (!se.enabled)
873  continue;
874 
875  try
876  {
877  wxString startup = se.script;
878  if (wxFileName(se.script).IsRelative())
880  if (!startup.IsEmpty())
881  {
882  if (!se.registered)
884  else if (!se.menu.IsEmpty())
885  Manager::Get()->GetScriptingManager()->RegisterScriptMenu(se.menu, startup, false);
886  else
887  Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script/function '%s' not loaded: invalid configuration"), se.script.wx_str()));
888  }
889  else
890  Manager::Get()->GetLogManager()->LogWarning(F(_("Startup script '%s' not found"), se.script.wx_str()));
891  }
892  catch (SquirrelError& exception)
893  {
895  }
896  }
897  }
898 }
899 
900 void MainFrame::PluginsUpdated(cb_unused cbPlugin* plugin, cb_unused int status)
901 {
902  Freeze();
903 
904  // menu
905  RecreateMenuBar();
906 
907  // update view->toolbars because we re-created the menubar
908  PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
909  for (unsigned int i = 0; i < plugins.GetCount(); ++i)
910  {
911  cbPlugin* plug = plugins[i]->plugin;
912  const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plug);
913  if (!info)
914  continue;
915 
916  if (m_PluginsTools[plug]) // if plugin has a toolbar
917  {
918  // toolbar exists; add the menu item
919  wxMenu* viewToolbars = nullptr;
920  GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
921  if (viewToolbars)
922  {
923  if (viewToolbars->FindItem(info->title) != wxNOT_FOUND)
924  continue;
925  wxMenuItem* item = AddPluginInMenus(viewToolbars, plug,
926  (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnToggleBar,
927  -1, true);
928  if (item)
929  {
930  item->Check(IsWindowReallyShown(m_PluginsTools[plug]));
931  }
932  }
933  }
934  }
935 
936  Thaw();
937 }
938 
940 {
941  Freeze();
942 
943  wxMenuBar* m = GetMenuBar();
944  SetMenuBar(nullptr); // unhook old menubar
945  CreateMenubar(); // create new menubar
946  delete m; // delete old menubar
947 
948  // update layouts menu
949  for (LayoutViewsMap::iterator it = m_LayoutViews.begin(); it != m_LayoutViews.end(); ++it)
950  {
951  if (it->first.IsEmpty())
952  continue;
953  SaveViewLayout(it->first, it->second,
954  m_LayoutMessagePane[it->first],
955  it->first == m_LastLayoutName);
956  }
957 
958  Thaw();
959 }
960 
962 {
964  Manager::Get()->ProcessEvent(event);
965 
966  int tmpidx;
967  wxMenuBar* mbar=nullptr;
968  wxMenu *tools=nullptr, *plugs=nullptr, *pluginsM=nullptr;
969  wxMenuItem *tmpitem=nullptr;
970 
971  wxXmlResource* xml_res = wxXmlResource::Get();
973  xml_res->Load(resPath + _T("/resources.zip#zip:main_menu.xrc"));
974  Manager::Get()->GetLogManager()->DebugLog(_T("Loading menubar..."));
975  mbar = xml_res->LoadMenuBar(_T("main_menu_bar"));
976  if (!mbar)
977  mbar = new wxMenuBar(); // Some error happened.
978  if (mbar)
979  SetMenuBar(mbar);
980 
981  // Find Menus that we'll change later
982 
983  tmpidx = mbar->FindMenu(_("&Edit"));
984  if (tmpidx!=wxNOT_FOUND)
985  {
986  wxMenu *hl=nullptr;
987  mbar->FindItem(idEditHighlightModeText, &hl);
988  if (hl)
989  {
991  if (colour_set)
992  {
993  wxArrayString langs = colour_set->GetAllHighlightLanguages();
994  for (size_t i = 0; i < langs.GetCount(); ++i)
995  {
996  if (i > 0 && !(i % 20))
997  hl->Break(); // break into columns every 20 items
998  int id = wxNewId();
999  hl->AppendRadioItem(id, langs[i],
1000  wxString::Format(_("Switch highlighting mode for current document to \"%s\""), langs[i].wx_str()));
1001  Connect(id, -1, wxEVT_COMMAND_MENU_SELECTED,
1002  (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
1004  }
1005  }
1006  }
1008  wxMenu* editMenu = mbar->GetMenu(tmpidx);
1009  if ( info
1010  && ( ( info->Language >= wxLANGUAGE_CHINESE
1011  && info->Language <= wxLANGUAGE_CHINESE_TAIWAN )
1012  || info->Language == wxLANGUAGE_JAPANESE
1013  || info->Language == wxLANGUAGE_KOREAN ) )
1014  {
1015  editMenu->Append(idEditCompleteCode, _("Complete code\tShift-Space"));
1016  }
1017  else
1018  editMenu->Append(idEditCompleteCode, _("Complete code\tCtrl-Space"));
1019  }
1020 
1021  tmpidx = mbar->FindMenu(_("&Tools"));
1022  if (tmpidx!=wxNOT_FOUND)
1023  tools = mbar->GetMenu(tmpidx);
1024 
1025  tmpidx = mbar->FindMenu(_("P&lugins"));
1026  if (tmpidx!=wxNOT_FOUND)
1027  plugs = mbar->GetMenu(tmpidx);
1028 
1029  if ((tmpitem = mbar->FindItem(idHelpPlugins,nullptr)))
1030  pluginsM = tmpitem->GetSubMenu();
1031 
1032  m_ToolsMenu = tools ? tools : new wxMenu();
1033  m_PluginsMenu = plugs ? plugs : new wxMenu();
1034  m_HelpPluginsMenu = pluginsM ? pluginsM : new wxMenu();
1035 
1036  // core modules: create menus
1037  if (!Manager::IsBatchBuild())
1038  static_cast<ProjectManagerUI*>(m_pPrjManUI)->CreateMenu(mbar);
1039  Manager::Get()->GetDebuggerManager()->SetMenuHandler(m_debuggerMenuHandler);
1040 
1041  // ask all plugins to rebuild their menus
1042  PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1043  for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1044  {
1045  cbPlugin* plug = plugins[i]->plugin;
1046  if (plug && plug->IsAttached())
1047  {
1048  if (plug->GetType() == ptTool)
1049  DoAddPlugin(plug);
1050  else
1051  {
1052  AddPluginInHelpPluginsMenu(plug);
1053  try
1054  {
1055  plug->BuildMenu(mbar);
1056  }
1057  catch (cbException& e)
1058  {
1059  e.ShowErrorMessage();
1060  }
1061  }
1062  }
1063  }
1064 
1065  Manager::Get()->GetToolsManager()->BuildToolsMenu(m_ToolsMenu);
1066 
1067  // Ctrl+Tab workaround for non windows platforms:
1068  if ((platform::carbon) || (platform::gtk))
1069  {
1070  // Find the menu item for tab switching:
1071  tmpidx = mbar->FindMenu(_("&View"));
1072  if (tmpidx != wxNOT_FOUND)
1073  {
1074  wxMenu* view = mbar->GetMenu(tmpidx);
1075  wxMenuItem* switch_item = view->FindItem(idViewSwitchTabs);
1076  if (switch_item)
1077  {
1078  // Change the accelerator for this menu item:
1079  wxString accel;
1080  if (platform::carbon)
1081  accel = wxT("Alt+Tab");
1082  else if (platform::gtk)
1083  accel = wxT("Ctrl+,");
1084  switch_item->SetItemLabel(wxString(_("S&witch tabs")) + wxT("\t") + accel);
1085  }
1086  }
1087  }
1088 
1089  SetMenuBar(mbar);
1090  InitializeRecentFilesHistory();
1091 
1093  Manager::Get()->ProcessEvent(event2);
1094 }
1095 
1097 {
1098  if (m_pToolbar)
1099  {
1100  SetToolBar(nullptr);
1101  m_pToolbar = nullptr;
1102  }
1103 
1104  wxString xrcToolbarName(_T("main_toolbar"));
1105  if (m_SmallToolBar) // Insert logic here
1106  xrcToolbarName += _T("_16x16");
1107 
1108  wxXmlResource* xml_res = wxXmlResource::Get();
1110  xml_res->Load(resPath + _T("/resources.zip#zip:") + xrcToolbarName + _T("*.xrc"));
1111  Manager::Get()->GetLogManager()->DebugLog(_T("Loading toolbar..."));
1112 
1113  m_pToolbar = Manager::Get()->CreateEmptyToolbar();
1114  Manager::Get()->AddonToolBar(m_pToolbar, xrcToolbarName);
1115 
1116  m_pToolbar->Realize();
1117 
1118  // Right click on the main toolbar will popup a context menu
1119  m_pToolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this);
1120 
1121  m_pToolbar->SetInitialSize();
1122 
1123  // Right click on the debugger toolbar will popup a context menu
1124  m_debuggerToolbarHandler->GetToolbar()->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this );
1125 
1126  std::vector<ToolbarInfo> toolbars;
1127 
1128  toolbars.push_back(ToolbarInfo(m_pToolbar, wxAuiPaneInfo().Name(wxT("MainToolbar")).Caption(_("Main Toolbar")), 0));
1129  toolbars.push_back(ToolbarInfo(m_debuggerToolbarHandler->GetToolbar(),
1130  wxAuiPaneInfo(). Name(wxT("DebuggerToolbar")).Caption(_("Debugger Toolbar")),
1131  2));
1132 
1133  // ask all plugins to rebuild their toolbars
1134  PluginElementsArray plugins = Manager::Get()->GetPluginManager()->GetPlugins();
1135  for (unsigned int i = 0; i < plugins.GetCount(); ++i)
1136  {
1137  cbPlugin* plug = plugins[i]->plugin;
1138  if (plug && plug->IsAttached())
1139  {
1140  ToolbarInfo info = DoAddPluginToolbar(plug);
1141  if (info.toolbar)
1142  {
1143  toolbars.push_back(info);
1144  // support showing context menu of the plugins' toolbar
1145  info.toolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
1146  wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this );
1147  }
1148  }
1149  }
1150 
1151  std::sort(toolbars.begin(), toolbars.end());
1152 
1153  int row = 0, position = 0, rowLength = 0;
1154  int maxLength = GetSize().x;
1155 
1156  for (std::vector<ToolbarInfo>::iterator it = toolbars.begin(); it != toolbars.end(); ++it)
1157  {
1158  rowLength += it->toolbar->GetSize().x;
1159  if (rowLength >= maxLength)
1160  {
1161  row++;
1162  position = 0;
1163  rowLength = it->toolbar->GetSize().x;
1164  }
1165  wxAuiPaneInfo paneInfo(it->paneInfo);
1166  m_LayoutManager.AddPane(it->toolbar, paneInfo.ToolbarPane().Top().Row(row).Position(position));
1167 
1168  position += it->toolbar->GetSize().x;
1169  }
1170  DoUpdateLayout();
1171 
1173  SetToolBar(nullptr);
1174 }
1175 
1176 void MainFrame::AddToolbarItem(int id, const wxString& title, const wxString& shortHelp, const wxString& longHelp, const wxString& image)
1177 {
1178  m_pToolbar->AddTool(id, title, cbLoadBitmap(image, wxBITMAP_TYPE_PNG));
1179  m_pToolbar->SetToolShortHelp(id, shortHelp);
1180  m_pToolbar->SetToolLongHelp(id, longHelp);
1181 }
1182 
1184 {
1185  m_ScanningForPlugins = true;
1186  m_PluginIDsMap.clear();
1187 
1188  PluginManager* m_PluginManager = Manager::Get()->GetPluginManager();
1189 
1190  // user paths first
1192  Manager::Get()->GetLogManager()->Log(_("Scanning for plugins in ") + path);
1193  int count = m_PluginManager->ScanForPlugins(path);
1194 
1195  // global paths
1196  path = ConfigManager::GetPluginsFolder(true);
1197  Manager::Get()->GetLogManager()->Log(_("Scanning for plugins in ") + path);
1198  count += m_PluginManager->ScanForPlugins(path);
1199 
1200  // actually load plugins
1201  if (count > 0)
1202  {
1203  Manager::Get()->GetLogManager()->Log(_("Loading:"));
1204  m_PluginManager->LoadAllPlugins();
1205  }
1206 
1209  m_ScanningForPlugins = false;
1210 }
1211 
1212 wxMenuItem* MainFrame::AddPluginInMenus(wxMenu* menu, cbPlugin* plugin, wxObjectEventFunction callback, int pos, bool checkable)
1213 {
1214  wxMenuItem* item = nullptr;
1215  if (!plugin || !menu)
1216  return item;
1217 
1218  const PluginInfo* info = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1219  if (!info)
1220  return nullptr;
1221 
1222  PluginIDsMap::iterator it;
1223  for (it = m_PluginIDsMap.begin(); it != m_PluginIDsMap.end(); ++it)
1224  {
1225  if (it->second == info->name)
1226  {
1227  item = menu->FindItem(it->first);
1228  if (item)
1229  return item;
1230  }
1231  }
1232 
1233  int id = wxNewId();
1234  wxString title = info->title + (menu == m_HelpPluginsMenu ? _T("...") : wxEmptyString);
1235  m_PluginIDsMap[id] = info->name;
1236  if (pos == -1)
1237  pos = menu->GetMenuItemCount();
1238 
1239  while(!item)
1240  {
1241  if (!pos || title.CmpNoCase(menu->FindItemByPosition(pos - 1)->GetItemLabelText()) > 0)
1242  item = menu->Insert(pos, id, title, wxEmptyString, checkable ? wxITEM_CHECK : wxITEM_NORMAL);
1243 
1244  --pos;
1245  }
1246 
1247  Connect( id, wxEVT_COMMAND_MENU_SELECTED, callback );
1248  return item;
1249 }
1250 
1252 {
1253  // "Plugins" menu is special case because it contains "Manage plugins",
1254  // which must stay at the end of the menu
1255  // So we insert entries, not append...
1256 
1257  // this will insert a separator when the first plugin is added in the "Plugins" menu
1258  if (m_PluginsMenu->GetMenuItemCount() == 1)
1259  m_PluginsMenu->Insert(0, wxID_SEPARATOR, _T(""));
1260 
1261  AddPluginInMenus(m_PluginsMenu, plugin,
1262  (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnPluginsExecuteMenu,
1263  m_PluginsMenu->GetMenuItemCount() - 2);
1264 }
1265 
1267 {
1268  AddPluginInMenus(m_HelpPluginsMenu, plugin,
1269  (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnHelpPluginMenu);
1270 }
1271 
1273 {
1274  wxArrayString subs = Manager::Get()->GetConfigManager(_T("app"))->EnumerateSubPaths(_T("/main_frame/layout"));
1275  for (size_t i = 0; i < subs.GetCount(); ++i)
1276  {
1277  wxString name = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/name"));
1278  wxString layout = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/data"));
1279  wxString layoutMP = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/") + subs[i] + _T("/dataMessagePane"));
1280  SaveViewLayout(name, layout, layoutMP);
1281  }
1282  wxString deflayout = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/default"));
1283  LoadViewLayout(deflayout);
1284 
1285  // load manager and messages selected page
1286  if (m_pPrjManUI->GetNotebook())
1287  m_pPrjManUI->GetNotebook()->SetSelection(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left_block_selection"), 0));
1288  m_pInfoPane->SetSelection(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/bottom_block_selection"), 0));
1289 
1290  // Cryogen 23/3/10 wxAuiNotebook can't set it's own tab position once instantiated, for some reason. This code fails in InfoPane::InfoPane().
1291  // Moved here as this seems like a resonable place to do UI setup. Feel free to move it elsewhere.
1292  if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/infopane_tabs_bottom"), false))
1293  m_pInfoPane->SetWindowStyleFlag(m_pInfoPane->GetWindowStyleFlag() | wxAUI_NB_BOTTOM);
1294 
1295 }
1296 
1298 {
1299 #ifndef __WXMAC__
1300  int x = 0;
1301  int y = 0;
1302 #else
1303  int x = 0;
1304  int y = wxSystemSettings::GetMetric(wxSYS_MENU_Y, this); // make sure it doesn't hide under the menu bar
1305 #endif
1306  int w = 1000;
1307  int h = 800;
1308 
1309  // obtain display index used last time
1310  int last_display_index = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/display"), 0);
1311  // load window size and position
1312  wxRect rect(Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/left"), x),
1313  Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/top"), y),
1314  Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/width"), w),
1315  Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/main_frame/layout/height"), h));
1316  // maximize if needed
1317  bool maximized = Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/main_frame/layout/maximized"), true);
1318  Maximize(maximized); // toggle
1319 
1320  // set display, size and position
1321  int display_index_window = wxDisplay::GetFromWindow(this); // C::B usually starts on primary display...
1322  // ...but try to use display that was used last time, if still available:
1323  if ((last_display_index>=0) && (last_display_index<static_cast<int>(wxDisplay::GetCount())))
1324  display_index_window = static_cast<int>(last_display_index);
1325  int display_index = ((display_index_window>=0) ? display_index_window : 0);
1326 
1327  wxDisplay disp(display_index); // index might be wxNOT_FOUND (=-1) due to GetFromWindow call
1328  if (maximized)
1329  {
1330  rect = disp.GetClientArea(); // apply from display, overriding settings above
1331  rect.width -= 100;
1332  rect.height -= 100;
1333  }
1334  else
1335  {
1336  // Adjust to actual screen size. This is useful for portable C::B versions,
1337  // where the window might be out of screen when saving on a two-monitor
1338  // system an re-opening on a one-monitor system (on Windows, at least).
1339  wxRect displayRect = disp.GetClientArea();
1340  if ((displayRect.GetLeft() + displayRect.GetWidth()) < rect.GetLeft()) rect.SetLeft (displayRect.GetLeft() );
1341  if ((displayRect.GetLeft() + displayRect.GetWidth()) < rect.GetRight()) rect.SetRight (displayRect.GetRight() );
1342  if ((displayRect.GetTop() + displayRect.GetHeight()) < rect.GetTop()) rect.SetTop (displayRect.GetTop() );
1343  if ((displayRect.GetTop() + displayRect.GetHeight()) < rect.GetBottom()) rect.SetBottom(displayRect.GetBottom());
1344  }
1345 
1346  SetSize(rect);
1347 }
1348 
1350 {
1351  DoCheckCurrentLayoutForChanges(false);
1352 
1353  // first delete all previous layouts, otherwise they might remain
1354  // if the new amount of layouts is less than the previous, because only the first layouts will be overwritten
1355  wxArrayString subs = Manager::Get()->GetConfigManager(_T("app"))->EnumerateSubPaths(_T("/main_frame/layout"));
1356  for (size_t i = 0; i < subs.GetCount(); ++i)
1357  {
1358  Manager::Get()->GetConfigManager(_T("app"))->DeleteSubPath(_T("/main_frame/layout/") + subs[i]);
1359  }
1360 
1361  int count = 0;
1362  for (LayoutViewsMap::iterator it = m_LayoutViews.begin(); it != m_LayoutViews.end(); ++it)
1363  {
1364  if (it->first.IsEmpty())
1365  continue;
1366  ++count;
1367  wxString key = wxString::Format(_T("/main_frame/layout/view%d/"), count);
1368  Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("name"), it->first);
1369  Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("data"), it->second);
1370 
1371  if (!m_LayoutMessagePane[it->first].IsEmpty())
1372  Manager::Get()->GetConfigManager(_T("app"))->Write(key + _T("dataMessagePane"), m_LayoutMessagePane[it->first]);
1373  }
1374 
1375  // save manager and messages selected page
1376  if (m_pPrjManUI->GetNotebook())
1377  {
1378  int selection = m_pPrjManUI->GetNotebook()->GetSelection();
1379  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/left_block_selection"), selection);
1380  }
1381  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/bottom_block_selection"), m_pInfoPane->GetSelection());
1382 
1383  // save display, window size and position
1384  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/display"), wxDisplay::GetFromWindow(this));
1385  if (!IsMaximized() && !IsIconized())
1386  {
1387  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/left"), GetPosition().x);
1388  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/top"), GetPosition().y);
1389  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/width"), GetSize().x);
1390  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/height"), GetSize().y);
1391  }
1392  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/maximized"), IsMaximized());
1393 }
1394 
1395 void MainFrame::LoadViewLayout(const wxString& name, bool isTemp)
1396 {
1397  if (m_LastLayoutName != name && !DoCheckCurrentLayoutForChanges(true))
1398  return;
1399 
1400  m_LastLayoutIsTemp = isTemp;
1401 
1402  wxString layout = m_LayoutViews[name];
1403  wxString layoutMP = m_LayoutMessagePane[name];
1404  if (layoutMP.IsEmpty())
1405  layoutMP = m_LayoutMessagePane[gDefaultLayout];
1406  if (layout.IsEmpty())
1407  {
1408  layout = m_LayoutViews[gDefaultLayout];
1409  SaveViewLayout(name, layout, layoutMP, false);
1410  DoSelectLayout(name);
1411  }
1412  else
1413  DoSelectLayout(name);
1414 
1415  // first load taborder of MessagePane, so LoadPerspective can restore the last selected tab
1416  m_pInfoPane->LoadTabOrder(layoutMP);
1417  m_LayoutManager.LoadPerspective(layout, false);
1418 
1419  DoUpdateLayout();
1420 
1421  m_PreviousLayoutName = m_LastLayoutName;
1422  m_LastLayoutName = name;
1423  m_LastLayoutData = layout;
1424  m_LastMessagePaneLayoutData = layoutMP;
1425 
1427  evt.layout = name;
1428  Manager::Get()->ProcessEvent(evt);
1429 }
1430 
1431 void MainFrame::SaveViewLayout(const wxString& name, const wxString& layout, const wxString& layoutMP, bool select)
1432 {
1433  if (name.IsEmpty())
1434  return;
1435  m_LayoutViews[name] = layout;
1436  m_LayoutMessagePane[name] = layoutMP;
1437  wxMenu* viewLayouts = nullptr;
1438  GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
1439  if (viewLayouts && viewLayouts->FindItem(name) == wxNOT_FOUND)
1440  {
1441  int id = wxNewId();
1442  viewLayouts->InsertCheckItem(viewLayouts->GetMenuItemCount() - 3, id, name, wxString::Format(_("Switch to %s perspective"), name.wx_str()));
1443  Connect( id, wxEVT_COMMAND_MENU_SELECTED,
1444  (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnViewLayout);
1445  m_PluginIDsMap[id] = name;
1446  }
1447  if (select)
1448  {
1449  DoSelectLayout(name);
1450  m_LastLayoutName = name;
1451  }
1452 }
1453 
1454 bool MainFrame::LayoutDifferent(const wxString& layout1,const wxString& layout2,const wxString& delimiter)
1455 {
1456  wxStringTokenizer strTok;
1457  unsigned long j;
1458 
1459  strTok.SetString(layout1, delimiter);
1460  wxArrayString arLayout1;
1461  while(strTok.HasMoreTokens())
1462  {
1463  wxStringTokenizer strTokColon(strTok.GetNextToken(), _T(";"));
1464  while(strTokColon.HasMoreTokens())
1465  {
1466  wxString theToken = strTokColon.GetNextToken();
1467  if (theToken.StartsWith(_T("state=")))
1468  {
1469  theToken=theToken.Right(theToken.Len() - wxString(_T("state=")).Len());
1470  theToken.ToULong(&j);
1471  // we filter out the hidden/show state
1472  theToken=wxString::Format(_("state=%lu"),j & wxAuiPaneInfo::optionHidden);
1473  }
1474  arLayout1.Add(theToken);
1475  }
1476  }
1477 
1478  strTok.SetString(layout2, delimiter);
1479  wxArrayString arLayout2;
1480  while(strTok.HasMoreTokens())
1481  {
1482  wxStringTokenizer strTokColon(strTok.GetNextToken(), _T(";"));
1483  while(strTokColon.HasMoreTokens())
1484  {
1485  wxString theToken = strTokColon.GetNextToken();
1486  if (theToken.StartsWith(_T("state=")))
1487  {
1488  theToken=theToken.Right(theToken.Len() - wxString(_T("state=")).Len());
1489  theToken.ToULong(&j);
1490  // we filter out the hidden/show state
1491  theToken=wxString::Format(_("state=%lu"),j & wxAuiPaneInfo::optionHidden);
1492  }
1493  arLayout2.Add(theToken);
1494  }
1495  }
1496 
1497  arLayout1.Sort();
1498  arLayout2.Sort();
1499 
1500  return arLayout1 != arLayout2;
1501 }
1502 
1503 bool MainFrame::LayoutMessagePaneDifferent(const wxString& layout1,const wxString& layout2, bool checkSelection)
1504 {
1505  wxStringTokenizer strTok;
1506  wxArrayString arLayout1;
1507  wxArrayString arLayout2;
1508 
1509  strTok.SetString(layout1.BeforeLast('|'), _T(";"));
1510  while (strTok.HasMoreTokens())
1511  {
1512  arLayout1.Add(strTok.GetNextToken());
1513  }
1514 
1515  strTok.SetString(layout2.BeforeLast('|'), _T(";"));
1516  while (strTok.HasMoreTokens())
1517  {
1518  arLayout2.Add(strTok.GetNextToken());
1519  }
1520 
1521  if (checkSelection)
1522  {
1523  arLayout1.Add(layout1.AfterLast('|'));
1524  arLayout2.Add(layout2.AfterLast('|'));
1525  }
1526  arLayout1.Sort();
1527  arLayout2.Sort();
1528 
1529  return arLayout1 != arLayout2;
1530 }
1531 
1533 {
1534  DoFixToolbarsLayout();
1535  wxString lastlayout = m_LayoutManager.SavePerspective();
1536  wxString lastmessagepanelayout = m_pInfoPane->SaveTabOrder();
1537  if (!m_LastLayoutName.IsEmpty() &&
1538  (LayoutDifferent(lastlayout, m_LastLayoutData) ||
1539  LayoutMessagePaneDifferent(lastmessagepanelayout, m_LastMessagePaneLayoutData, Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/save_selection_change_in_mp"), true)) ))
1540  {
1541  AnnoyingDialog dlg(_("Layout changed"),
1542  wxString::Format(_("The perspective '%s' has changed. Do you want to save it?"), m_LastLayoutName.wx_str()),
1545  // partial fix for bug 18970 (fix is incomplete to prevent the user from saving 'rtCANCEL')
1547  switch (dlg.ShowModal())
1548  {
1549  case AnnoyingDialog::rtYES:
1550  SaveViewLayout(m_LastLayoutName, lastlayout, lastmessagepanelayout, false);
1551  break;
1553  DoSelectLayout(m_LastLayoutName);
1554  return false;
1555  default:
1556  break;
1557  }
1558  }
1559  return true;
1560 }
1561 
1563 {
1564  // because the user might change the toolbar icons size, we must cater for it...
1565  wxAuiPaneInfoArray& panes = m_LayoutManager.GetAllPanes();
1566  for (size_t i = 0; i < panes.GetCount(); ++i)
1567  {
1568  wxAuiPaneInfo& info = panes[i];
1569  if (info.state & wxAuiPaneInfo::optionToolbar)
1570  {
1571  info.best_size = info.window->GetBestSize();
1572  info.floating_size = wxDefaultSize;
1573  }
1574  }
1575 }
1576 
1578 {
1579  wxMenu* viewLayouts = nullptr;
1580  GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
1581  if (viewLayouts)
1582  {
1583  wxMenuItemList& items = viewLayouts->GetMenuItems();
1584  for (size_t i = 0; i < items.GetCount(); ++i)
1585  {
1586  if (!items[i]->IsCheckable())
1587  continue;
1588 #if wxCHECK_VERSION(3, 0, 0)
1589  items[i]->Check(items[i]->GetItemLabel().IsSameAs(name));
1590 #else
1591  items[i]->Check(items[i]->GetText().IsSameAs(name));
1592 #endif
1593  }
1594 
1595  if (!m_LastLayoutIsTemp)
1596  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/main_frame/layout/default"), name);
1597  }
1598 }
1599 
1601 {
1602  cbStatusBar *sbar = (cbStatusBar *)GetStatusBar();
1603  if (!sbar)
1604  return;
1605  plugin->CreateStatusField(sbar);
1606  sbar->AdjustFieldsSize();
1607 }
1608 
1609 inline void InitToolbar(wxToolBar *tb)
1610 {
1611  tb->SetInitialSize();
1612 }
1613 
1615 {
1616  ToolbarInfo info;
1618  if (plugin->BuildToolBar(info.toolbar))
1619  {
1620  info.priority = plugin->GetToolBarPriority();
1621  SetToolBar(nullptr);
1622  InitToolbar(info.toolbar);
1623 
1624  // add View->Toolbars menu item for toolbar
1625  wxMenu* viewToolbars = nullptr;
1626  GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
1627  if (viewToolbars)
1628  {
1629  wxMenuItem* item = AddPluginInMenus(viewToolbars, plugin,
1630  (wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)&MainFrame::OnToggleBar,
1631  -1, true);
1632  if (item)
1633  {
1634  item->Check(true);
1635  m_PluginsTools[plugin] = info.toolbar;
1636  }
1637  }
1638 
1639  const PluginInfo* pluginInfo = Manager::Get()->GetPluginManager()->GetPluginInfo(plugin);
1640  if (!pluginInfo)
1641  cbThrow(_T("No plugin info?!?"));
1642 
1643  info.paneInfo.Name(pluginInfo->name + _T("Toolbar")).Caption(pluginInfo->title + _(" Toolbar"));
1644  }
1645  else
1646  {
1647  delete info.toolbar;
1648  info.toolbar = nullptr;
1649  }
1650  return info;
1651 }
1652 
1654 {
1655  //Manager::Get()->GetLogManager()->DebugLog(_T("Adding plugin: %s"), plugin->GetInfo()->name.wx_str());
1656  AddPluginInHelpPluginsMenu(plugin);
1657  if (plugin->GetType() == ptTool)
1658  {
1659  AddPluginInPluginsMenu(plugin);
1660  }
1661  // offer menu and toolbar space for other plugins
1662  else
1663  {
1664  // menu
1665  try
1666  {
1667  wxMenuBar* mbar = GetMenuBar();
1668  plugin->BuildMenu(mbar);
1669  }
1670  catch (cbException& e)
1671  {
1672  e.ShowErrorMessage();
1673  }
1674  // Don't load the toolbars during the initial loading of the plugins, this code should be executed
1675  // only when a single plugins is loaded from the Plugins -> Manager ... window.
1676  if (!m_ScanningForPlugins)
1677  {
1678  // Create the toolbar for the plugin if there is one.
1679  const ToolbarInfo &toolbarInfo = DoAddPluginToolbar(plugin);
1680  if (toolbarInfo.toolbar)
1681  {
1682  // Place the new toolbar at the bottom of the toolbar pane. Try to reuse the last row
1683  // if there is enough space in it, otherwise place the new toolbar at a new row.
1684  int row = 0;
1685  const wxAuiPaneInfoArray &panes = m_LayoutManager.GetAllPanes();
1686  for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1687  {
1688  const wxAuiPaneInfo &info = panes[ii];
1689  if (info.IsToolbar())
1690  row = std::max(row, info.dock_row);
1691  }
1692  int minX = 100000, maxX = -100000;
1693  int position = 0;
1694  for (size_t ii = 0; ii < panes.GetCount(); ++ii)
1695  {
1696  const wxAuiPaneInfo &info = panes[ii];
1697  if (info.IsToolbar() && info.dock_row == row && info.window)
1698  {
1699  const wxPoint &pt = info.window->GetPosition();
1700  minX = std::min(minX, pt.x + info.window->GetSize().x);
1701  maxX = std::max(maxX, pt.x + info.window->GetSize().x);
1702  position = std::max(position, info.dock_pos);
1703  }
1704  }
1705  if (maxX + toolbarInfo.toolbar->GetSize().x <= GetSize().x)
1706  position++;
1707  else
1708  {
1709  row++;
1710  position = 0;
1711  }
1712  wxAuiPaneInfo paneInfo(toolbarInfo.paneInfo);
1713  m_LayoutManager.AddPane(toolbarInfo.toolbar, paneInfo. ToolbarPane().Top().Row(row).Position(position));
1714  // Add the event handler for mouse right click
1715  toolbarInfo.toolbar->Connect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED,
1716  wxCommandEventHandler(MainFrame::OnToolBarRightClick), NULL, this);
1717 
1718  DoUpdateLayout();
1719  }
1720  }
1721  DoAddPluginStatusField(plugin);
1722  }
1723 }
1724 
1725 bool MainFrame::Open(const wxString& filename, bool addToHistory)
1726 {
1727  wxFileName fn(filename);
1728  fn.Normalize(); // really important so that two same files with different names are not loaded twice
1729  wxString name = fn.GetFullPath();
1730  LogManager *logger = Manager::Get()->GetLogManager();
1731  logger->DebugLog(_T("Opening file ") + name);
1732  bool ret = OpenGeneric(name, addToHistory);
1733  if (!ret)
1734  logger->LogError(wxString::Format(wxT("Opening file '%s' failed!"), name.wx_str()));
1735 
1736  return ret;
1737 }
1738 
1740 {
1741  wxFileDialog dlg(this,
1742  caption,
1743  wxEmptyString,
1744  wxEmptyString,
1745  filter,
1746  wxFD_OPEN | compatibility::wxHideReadonly);
1747  wxString sel;
1748  PlaceWindow(&dlg);
1749  if (dlg.ShowModal() == wxID_OK)
1750  sel = dlg.GetPath();
1751  return sel;
1752 }
1753 
1754 bool MainFrame::OpenGeneric(const wxString& filename, bool addToHistory)
1755 {
1756  if (filename.IsEmpty())
1757  return false;
1758 
1759  wxFileName fname(filename); fname.ClearExt(); fname.SetExt(_T("cbp"));
1760  switch ( FileTypeOf(filename) )
1761  {
1762  //
1763  // Workspace
1764  //
1765  case ftCodeBlocksWorkspace:
1766  // verify that it's not the same as the one already open
1767  if (filename == Manager::Get()->GetProjectManager()->GetWorkspace()->GetFilename())
1768  return true;
1769  else
1770  {
1771  if ( DoCloseCurrentWorkspace() )
1772  {
1773  wxBusyCursor wait; // loading a worspace can take some time -> showhourglass
1774  ShowHideStartPage(true); // hide startherepage, so we can use full tab-range
1775  bool ret = Manager::Get()->GetProjectManager()->LoadWorkspace(filename);
1776  if (!ret)
1777  ShowHideStartPage(); // show/hide startherepage, dependant of settings, if loading failed
1778  else if (addToHistory)
1779  m_projectsHistory.AddToHistory(Manager::Get()->GetProjectManager()->GetWorkspace()->GetFilename());
1780  return ret;
1781  }
1782  else
1783  return false;
1784  }
1785  break;
1786 
1787  //
1788  // Project
1789  //
1790  case ftCodeBlocksProject:
1791  {
1792  // Make a check whether the project exists in current workspace
1794  if (!prj)
1795  {
1796  wxBusyCursor wait; // loading a workspace can take some time -> showhourglass
1797  return DoOpenProject(filename, addToHistory);
1798  }
1799  else
1800  {
1801  // NOTE (Morten#1#): A message here will prevent batch-builds from working and is shown sometimes even if correct
1802  Manager::Get()->GetProjectManager()->SetProject(prj, false);
1803  return true;
1804  }
1805  }
1806  //
1807  // Source files
1808  //
1809  case ftHeader:
1810  // fallthrough
1811  case ftSource:
1812  // fallthrough
1813  case ftTemplateSource:
1814  // fallthrough
1815  case ftResource:
1816  return DoOpenFile(filename, addToHistory);
1817  //
1818  // For all other files, ask MIME plugin for a suitable handler
1819  //
1820  default:
1821  {
1823  // warn user that "Files extension handler" is disabled
1824  if (!plugin)
1825  {
1826  cbMessageBox(_("Could not open file ") + filename + _(",\nbecause no extension handler could be found."), _("Error"), wxICON_ERROR);
1827  return false;
1828  }
1829  if (plugin->OpenFile(filename) == 0)
1830  {
1831  m_filesHistory.AddToHistory(filename);
1832  return true;
1833  }
1834  return false;
1835  }
1836  }
1837  return true;
1838 }
1839 
1840 bool MainFrame::DoOpenProject(const wxString& filename, bool addToHistory)
1841 {
1842 // Manager::Get()->GetLogManager()->DebugLog(_T("Opening project '%s'"), filename.wx_str());
1843  if (!wxFileExists(filename))
1844  {
1845  cbMessageBox(_("The project file does not exist..."), _("Error"), wxICON_ERROR);
1846  return false;
1847  }
1848 
1849  ShowHideStartPage(true); // hide startherepage, so we can use full tab-range
1850  cbProject* prj = Manager::Get()->GetProjectManager()->LoadProject(filename, true);
1851  if (prj)
1852  {
1853  if (addToHistory)
1854  m_projectsHistory.AddToHistory(prj->GetFilename());
1855  return true;
1856  }
1857  ShowHideStartPage(); // show/hide startherepage, dependant of settings, if loading failed
1858  return false;
1859 }
1860 
1861 bool MainFrame::DoOpenFile(const wxString& filename, bool addToHistory)
1862 {
1863  cbEditor* ed = Manager::Get()->GetEditorManager()->Open(filename);
1864  if (ed)
1865  {
1866  // Cryogen 24/3/10 Activate the editor after opening. Partial fix for bug #14087.
1867  ed->Activate();
1868  if (addToHistory)
1869  m_filesHistory.AddToHistory(ed->GetFilename());
1870  return true;
1871  }
1872  return false;
1873 }
1874 
1876 {
1878 }
1879 
1881 {
1882  wxClientDC dc(this);
1883  wxFont font = dc.GetFont();
1884  int h;
1885  size_t num = 0;
1886 
1887  wxCoord widths[16]; // 16 max
1888  widths[num++] = -1; // main field
1889 
1890  dc.GetTextExtent(_(" Highlight Button "), &widths[num++], &h);
1891  dc.GetTextExtent(_(" Windows (CR+LF) "), &widths[num++], &h);
1892  dc.GetTextExtent(_(" WINDOWS-1252 "), &widths[num++], &h);
1893  dc.GetTextExtent(_(" Line 12345, Col 123, Pos 123456 "), &widths[num++], &h);
1894  dc.GetTextExtent(_(" Overwrite "), &widths[num++], &h);
1895  dc.GetTextExtent(_(" Modified "), &widths[num++], &h);
1896  dc.GetTextExtent(_(" Read/Write "), &widths[num++], &h);
1897  dc.GetTextExtent(_(" name_of_profile "), &widths[num++], &h);
1898 
1899  wxStatusBar* sb = CreateStatusBar(num);
1900  if (!sb)
1901  return;
1902 
1903  SetStatusWidths(num, widths);
1904 
1905  // Highlightbutton
1906  wxRect rect;
1907  if (sb->GetFieldRect(1, rect))
1908  {
1909  m_pHighlightButton = new wxButton(sb, idHighlightButton, wxT("bla"), wxDefaultPosition, wxDefaultSize,
1911  // Adjust status bar height to fit the button.
1912  // This affects wx3.x build more than wx2.8 builds. At least on wxGTK.
1913  const int height = std::max(sb->GetMinHeight(), m_pHighlightButton->GetClientSize().GetHeight());
1914  sb->SetMinHeight(height);
1915  }
1916 }
1917 
1921 static void changeButtonLabel(wxButton &button, const wxString &text)
1922 {
1923  if (text != button.GetLabel())
1924  button.SetLabel(text);
1925 }
1926 
1928 {
1929  if (!GetStatusBar())
1930  return;
1932  return;
1933 
1935  wxString personality(Manager::Get()->GetPersonalityManager()->GetPersonality());
1936  if (ed)
1937  {
1938  cbStyledTextCtrl * const control = ed->GetControl();
1939 
1940  int panel = 0;
1941  int pos = control->GetCurrentPos();
1942  wxString msg;
1943  SetStatusText(ed->GetFilename(), panel++);
1944 
1945  // Highlightbutton
1946  if (m_pHighlightButton)
1947  {
1949  if (colour_set)
1950  changeButtonLabel(*m_pHighlightButton, colour_set->GetLanguageName(ed->GetLanguage()));
1951  else
1952  changeButtonLabel(*m_pHighlightButton, wxEmptyString);
1953  }
1954  // EOL mode
1955  panel++;
1956  switch (control->GetEOLMode())
1957  {
1958  case wxSCI_EOL_CRLF: msg = _T("Windows (CR+LF)"); break;
1959  case wxSCI_EOL_CR: msg = _T("Mac (CR)"); break;
1960  case wxSCI_EOL_LF: msg = _T("Unix (LF)"); break;
1961  default: break;
1962  }
1963  SetStatusText(msg, panel++);
1964  SetStatusText(ed->GetEncodingName(), panel++);
1965  msg.Printf(_("Line %d, Col %d, Pos %d"), control->GetCurrentLine() + 1, control->GetColumn(pos) + 1, pos);
1966  SetStatusText(msg, panel++);
1967  SetStatusText(control->GetOvertype() ? _("Overwrite") : _("Insert"), panel++);
1968 #if wxCHECK_VERSION(3, 0, 0)
1969  SetStatusText(ed->GetModified() ? _("Modified") : _T(""), panel++);
1970 #else
1971  SetStatusText(ed->GetModified() ? _("Modified") : wxEmptyString, panel++);
1972 #endif
1973  SetStatusText(control->GetReadOnly() ? _("Read only") : _("Read/Write"), panel++);
1974  SetStatusText(personality, panel++);
1975  }
1976  else
1977  {
1978  int panel = 0;
1980  if ( eb )
1981  SetStatusText(eb->GetFilename(), panel++);
1982  else
1983  SetStatusText(_("Welcome to ") + appglobals::AppName + _T("!"), panel++);
1984 
1985  // Highlightbutton
1986  if (m_pHighlightButton)
1987  changeButtonLabel(*m_pHighlightButton, wxEmptyString);
1988  panel++;
1989 
1990  SetStatusText(wxEmptyString, panel++);
1991  SetStatusText(wxEmptyString, panel++);
1992  SetStatusText(wxEmptyString, panel++);
1993  SetStatusText(wxEmptyString, panel++);
1994  SetStatusText(wxEmptyString, panel++);
1995  SetStatusText(wxEmptyString, panel++);
1996  SetStatusText(personality, panel++);
1997  }
1998 }
1999 
2000 void MainFrame::DoUpdateEditorStyle(cbAuiNotebook* target, const wxString& prefix, long defaultStyle)
2001 {
2002  if (!target)
2003  return;
2004 
2005  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
2006  target->SetTabCtrlHeight(1);
2007 
2008  long nbstyle = cfg->ReadInt(_T("/environment/tabs_style"), 0);
2009  switch (nbstyle)
2010  {
2011  case 1: // simple style
2012  target->SetArtProvider(new wxAuiSimpleTabArt());
2013  break;
2014 
2015  case 2: // VC 7.1 style
2016  target->SetArtProvider(new NbStyleVC71());
2017  break;
2018 
2019  case 3: // Firefox 2 style
2020  target->SetArtProvider(new NbStyleFF2());
2021  break;
2022 
2023  default: // default style
2024  #if defined(__WXGTK__) && (USE_GTK_NOTEBOOK) && !wxCHECK_VERSION(3, 0, 0)
2025  target->SetArtProvider(new NbStyleGTK());
2026  #else
2027  target->SetArtProvider(new wxAuiDefaultTabArt());
2028  #endif
2029  break;
2030  }
2031 
2032  target->SetTabCtrlHeight(-1);
2033 
2034  nbstyle = defaultStyle;
2035  if (cfg->ReadBool(_T("/environment/") + prefix + _T("_tabs_bottom")))
2036  nbstyle |= wxAUI_NB_BOTTOM;
2037 
2038  if (cfg->ReadBool(_T("/environment/tabs_list")))
2039  nbstyle |= wxAUI_NB_WINDOWLIST_BUTTON;
2040 
2041  target->SetWindowStyleFlag(nbstyle);
2042 }
2043 
2045 {
2046  long style = wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE | wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_MIDDLE_CLICK_CLOSE;
2047  long closestyle = Manager::Get()->GetConfigManager(_T("app"))->ReadInt(_T("/environment/tabs_closestyle"), 0);
2048  switch (closestyle)
2049  {
2050  case 1: // current tab
2051  style |= wxAUI_NB_CLOSE_ON_ACTIVE_TAB;
2052  break;
2053 
2054  case 2: // right side
2055  style |= wxAUI_NB_CLOSE_BUTTON;
2056  break;
2057 
2058  default: // all tabs (default)
2059  style |= wxAUI_NB_CLOSE_ON_ALL_TABS;
2060  break;
2061  }
2062 
2064 
2065  DoUpdateEditorStyle(an, _T("editor"), style | wxNO_FULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN);
2066  if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/hide_editor_tabs"),false))
2067  an->SetTabCtrlHeight(0);
2068 
2069  an = m_pInfoPane;
2070  DoUpdateEditorStyle(an, _T("infopane"), style);
2071 
2072  an = m_pPrjManUI->GetNotebook();
2073  DoUpdateEditorStyle(an, _T("project"), wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_TAB_MOVE);
2074 }
2075 
2077 {
2078  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
2079  wxAuiDockArt* art = m_LayoutManager.GetArtProvider();
2080 
2081 #ifndef __WXGTK__
2083 #else // #ifndef __WXGTK__
2084  // workaround for a wxWidgets-bug that makes C::B crash when a floating window gets docked and composite-effects are enabled
2086 #endif // #ifndef __WXGTK__
2087 
2088  art->SetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE, cfg->ReadInt(_T("/environment/aui/border_size"), art->GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE)));
2089  art->SetMetric(wxAUI_DOCKART_SASH_SIZE, cfg->ReadInt(_T("/environment/aui/sash_size"), art->GetMetric(wxAUI_DOCKART_SASH_SIZE)));
2090  art->SetMetric(wxAUI_DOCKART_CAPTION_SIZE, cfg->ReadInt(_T("/environment/aui/caption_size"), art->GetMetric(wxAUI_DOCKART_CAPTION_SIZE)));
2091  art->SetColour(wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR, cfg->ReadColour(_T("/environment/aui/active_caption_colour"), art->GetColour(wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR)));
2092  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)));
2093  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)));
2094  art->SetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR, cfg->ReadColour(_T("/environment/aui/inactive_caption_colour"), art->GetColour(wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR)));
2095  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)));
2096  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)));
2097 
2098  DoUpdateLayout();
2099 }
2100 
2102 {
2103  if (!m_StartupDone)
2104  return;
2105 
2106  DoFixToolbarsLayout();
2107  m_LayoutManager.Update();
2108 }
2109 
2111 {
2113  cbProject* prj = nullptr;
2114  if (ed && ed->IsBuiltinEditor())
2115  {
2116  ProjectFile* prjf = ((cbEditor*)ed)->GetProjectFile();
2117  if (prjf)
2118  prj = prjf->GetParentProject();
2119  }
2120  else
2122  wxString projname;
2123  wxString edname;
2124  wxString fulltitle;
2125  if (ed || prj)
2126  {
2127  if (prj)
2128  {
2129  if (Manager::Get()->GetProjectManager()->GetActiveProject() == prj)
2130  projname = wxString(_T(" [")) + prj->GetTitle() + _T("]");
2131  else
2132  projname = wxString(_T(" (")) + prj->GetTitle() + _T(")");
2133  }
2134  if (ed)
2135  edname = ed->GetTitle();
2136  fulltitle = edname + projname;
2137  if (!fulltitle.IsEmpty())
2138  fulltitle.Append(_T(" - "));
2139  }
2140  fulltitle.Append(appglobals::AppName);
2141  fulltitle.Append(_T(" "));
2142  fulltitle.Append(appglobals::AppVersion);
2143  SetTitle(fulltitle);
2144 }
2145 
2146 void MainFrame::ShowHideStartPage(bool forceHasProject, int forceState)
2147 {
2148 // Manager::Get()->GetLogManager()->LogWarning(_("Toggling start page"));
2149  if (Manager::IsBatchBuild())
2150  return;
2151 
2152  // we use the 'forceHasProject' param because when a project is opened
2153  // the EVT_PROJECT_OPEN event is fired *before* ProjectManager::GetProjects()
2154  // and ProjectManager::GetActiveProject() are updated...
2155 
2156  if (m_InitiatedShutdown)
2157  {
2159  if (sh)
2160  sh->Destroy();
2161  return;
2162  }
2163 
2164  bool show = !forceHasProject &&
2165  Manager::Get()->GetProjectManager()->GetProjects()->GetCount() == 0 &&
2166  Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/start_here_page"), true);
2167 
2168  if (forceState<0)
2169  show = false;
2170  if (forceState>0)
2171  show = true;
2172 
2174  if (show)
2175  {
2176  if (!sh)
2177  {
2178  sh = new StartHerePage(this, m_projectsHistory, m_filesHistory,
2179  Manager::Get()->GetEditorManager()->GetNotebook());
2180  }
2181  else
2182  static_cast<StartHerePage*>(sh)->Reload();
2183  }
2184  else if (!show && sh)
2185  sh->Destroy();
2186 
2187  DoUpdateAppTitle();
2188 }
2189 
2191 {
2192  if (Manager::IsBatchBuild())
2193  return;
2194  bool isVis = IsWindowReallyShown(m_pScriptConsole);
2196  evt.pWindow = m_pScriptConsole;
2197  Manager::Get()->ProcessEvent(evt);
2198 }
2199 
2201 {
2202  wxCommandEvent evt;
2203  evt.SetId(idFileNewProject);
2204  wxString link = event.GetString();
2205  if (link.IsSameAs(_T("CB_CMD_NEW_PROJECT")))
2206  OnFileNewWhat(evt);
2207  else if (link.IsSameAs(_T("CB_CMD_OPEN_PROJECT")))
2208  DoOnFileOpen(true);
2209 // else if (link.IsSameAs(_T("CB_CMD_CONF_ENVIRONMENT")))
2210 // OnSettingsEnvironment(evt);
2211 // else if (link.IsSameAs(_T("CB_CMD_CONF_EDITOR")))
2212 // Manager::Get()->GetEditorManager()->Configure();
2213 // else if (link.IsSameAs(_T("CB_CMD_CONF_COMPILER")))
2214 // OnSettingsCompilerDebugger(evt);
2215  else if (link.StartsWith(_T("CB_CMD_OPEN_HISTORY_")))
2216  {
2217  RecentItemsList *recent;
2218  recent = link.StartsWith(_T("CB_CMD_OPEN_HISTORY_PROJECT_")) ? &m_projectsHistory : &m_filesHistory;
2219  unsigned long item;
2220  link.AfterLast(_T('_')).ToULong(&item);
2221  --item;
2222  const wxString &filename = recent->GetHistoryFile(item);
2223  if (!filename.empty())
2224  {
2225  if ( !OpenGeneric(filename, true) )
2226  recent->AskToRemoveFileFromHistory(item);
2227  }
2228  }
2229  else if (link.StartsWith(_T("CB_CMD_DELETE_HISTORY_")))
2230  {
2231  RecentItemsList *recent;
2232  recent = link.StartsWith(_T("CB_CMD_DELETE_HISTORY_PROJECT_")) ? &m_projectsHistory : &m_filesHistory;
2233  unsigned long item;
2234  link.AfterLast(_T('_')).ToULong(&item);
2235  --item;
2236  recent->AskToRemoveFileFromHistory(item, false);
2237  }
2238  else if (link.IsSameAs(_T("CB_CMD_TIP_OF_THE_DAY")))
2239  ShowTips(true);
2240 }
2241 
2243 {
2244  m_filesHistory.Initialize();
2245  m_projectsHistory.Initialize();
2246 }
2247 
2249 {
2250  m_filesHistory.TerminateHistory();
2251  m_projectsHistory.TerminateHistory();
2252 }
2253 
2255 {
2256  wxString descr = wxEmptyString;
2257  cbProject* prj = NULL;
2258  if (eb && eb->IsBuiltinEditor())
2259  {
2260  ProjectFile* prjf = ((cbEditor*)eb)->GetProjectFile();
2261  if (prjf)
2262  prj = prjf->GetParentProject();
2263  }
2264  else
2266  if (prj)
2267  {
2268  descr = wxString(_("Project: ")) + _T("<b>") + prj->GetTitle() + _T("</b>");
2269  if (Manager::Get()->GetProjectManager()->GetActiveProject() == prj)
2270  descr += wxString(_(" (Active)"));
2271  descr += wxString(_T("<br>"));
2272  }
2273  if (eb)
2274  descr += eb->GetFilename();
2275  return descr;
2276 }
2277 
2279 // event handlers
2281 
2283 {
2284  wxString pluginName = m_PluginIDsMap[event.GetId()];
2285  if (!pluginName.IsEmpty())
2286  Manager::Get()->GetPluginManager()->ExecutePlugin(pluginName);
2287  else
2288  Manager::Get()->GetLogManager()->DebugLog(F(_T("No plugin found for ID %d"), event.GetId()));
2289 }
2290 
2292 {
2293  wxString pluginName = m_PluginIDsMap[event.GetId()];
2294  if (!pluginName.IsEmpty())
2295  {
2296  const PluginInfo* pi = Manager::Get()->GetPluginManager()->GetPluginInfo(pluginName);
2297  if (!pi)
2298  {
2299  Manager::Get()->GetLogManager()->DebugLog(_T("No plugin info for ") + pluginName);
2300  return;
2301  }
2302  dlgAboutPlugin dlg(this, pi);
2303  PlaceWindow(&dlg);
2304  dlg.ShowModal();
2305  }
2306  else
2307  Manager::Get()->GetLogManager()->DebugLog(F(_T("No plugin found for ID %d"), event.GetId()));
2308 }
2309 
2311 {
2312  int id = event.GetId();
2313  if (id != idFileNewEmpty)
2314  {
2315  // wizard-based
2316 
2318  if (id == idFileNewProject) tot = totProject;
2319  else if (id == idFileNewTarget) tot = totTarget;
2320  else if (id == idFileNewFile) tot = totFiles;
2321  else if (id == idFileNewCustom) tot = totCustom;
2322  else if (id == idFileNewUser) tot = totUser;
2323  else return;
2324 
2325  wxString filename;
2326  cbProject* prj = TemplateManager::Get()->New(tot, &filename);
2327  // verify that the open files are still in sync
2328  // the new file might have overwritten an existing one)
2330 
2331  // If both are empty it means that the wizard has failed
2332  if (!prj && filename.IsEmpty())
2333  return;
2334 
2335  // Send the new project event
2336  CodeBlocksEvent evtNew(cbEVT_PROJECT_NEW, 0, prj);
2338 
2339  if (prj)
2340  {
2341  prj->Save();
2342  prj->SaveAllFiles();
2343  }
2344 
2345  if (!filename.IsEmpty())
2346  {
2347  if (prj)
2348  m_projectsHistory.AddToHistory(filename);
2349  else
2350  m_filesHistory.AddToHistory(filename);
2351  }
2352  if (prj && tot == totProject) // Created project should be parsed
2353  {
2354  CodeBlocksEvent evtOpen(cbEVT_PROJECT_OPEN, 0, prj);
2356  }
2357  return;
2358  }
2359 
2360  // new empty file quick shortcut code below
2361 
2363  if (project)
2364  wxSetWorkingDirectory(project->GetBasePath());
2365  cbEditor* ed = Manager::Get()->GetEditorManager()->New();
2366 
2367  // initially start change-collection if configured on empty files
2368  if (ed)
2369  ed->GetControl()->SetChangeCollection(Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true));
2370 
2371  if (ed && ed->IsOK())
2372  m_filesHistory.AddToHistory(ed->GetFilename());
2373 
2374  if (!ed || !project)
2375  return;
2376 
2377  wxString oldname = ed->GetFilename();
2378  if (cbMessageBox(_("Do you want to add this new file in the active project (has to be saved first)?"),
2379  _("Add file to project"),
2381  ed->SaveAs() && ed->IsOK())
2382  {
2383  wxArrayInt targets;
2384  if (Manager::Get()->GetProjectManager()->AddFileToProject(ed->GetFilename(), project, targets) != 0)
2385  {
2386  ProjectFile* pf = project->GetFileByFilename(ed->GetFilename(), false);
2387  ed->SetProjectFile(pf);
2388  m_pPrjManUI->RebuildTree();
2389  }
2390  }
2391  // verify that the open files are still in sync
2392  // the new file might have overwritten an existing one)
2394 }
2395 
2396 bool MainFrame::OnDropFiles(wxCoord /*x*/, wxCoord /*y*/, const wxArrayString& files)
2397 {
2398  bool success = true; // Safe case initialisation
2399 
2400  // first check to see if a workspace is passed. If so, only this will be loaded
2401  wxString foundWorkspace;
2402  for (unsigned int i = 0; i < files.GetCount(); ++i)
2403  {
2404  FileType ft = FileTypeOf(files[i]);
2405  if (ft == ftCodeBlocksWorkspace || ft == ftMSVC6Workspace || ft == ftMSVC7Workspace)
2406  {
2407  foundWorkspace = files[i];
2408  break;
2409  }
2410  }
2411 
2412  if (!foundWorkspace.IsEmpty())
2413  success &= OpenGeneric(foundWorkspace);
2414  else
2415  {
2416  wxBusyCursor useless;
2417  wxPaintEvent e;
2418  ProcessEvent(e);
2419  for (unsigned int i = 0; i < files.GetCount(); ++i)
2420  success &= OpenGeneric(files[i]);
2421  }
2422  return success;
2423 }
2424 
2425 void MainFrame::OnFileNew(cb_unused wxCommandEvent& event)
2426 {
2427  wxMenu* popup = nullptr;
2428  wxMenuBar* bar = GetMenuBar();
2429  if (!bar)
2430  return;
2431 
2432  bar->FindItem(idFileNewProject, &popup);
2433  if (popup)
2434  {
2435  popup = CopyMenu(popup);
2436  if (popup)
2437  {
2438  PopupMenu(popup); // this will lead us in OnFileNewWhat() - the meat is there ;)
2439  delete popup;
2440  }
2441  }
2442 }
2443 
2444 // in case we are opening a project (bProject == true) we do not want to interfere
2445 // with 'last type of files' (probably the call was open (existing) project on the
2446 // start here page --> so we know it's a project --> set the filter accordingly
2447 // but as said don't force the 'last used type of files' to change, that should
2448 // only change when an open file is carried out (so (source) file <---> project (file) )
2449 // TODO : when regular file open and user manually sets filter to project files --> will change
2450 // the last type : is that expected behaviour ???
2451 void MainFrame::DoOnFileOpen(bool bProject)
2452 {
2454  // the value returned by GetIndexForFilterAll() is updated by GetFilterString()
2455  int StoredIndex = FileFilters::GetIndexForFilterAll();
2456  wxString Path;
2457  ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("app"));
2458  if (mgr)
2459  {
2460  if (!bProject)
2461  {
2462  wxString Filter = mgr->Read(_T("/file_dialogs/file_new_open/filter"));
2463  if (!Filter.IsEmpty())
2464  FileFilters::GetFilterIndexFromName(Filters, Filter, StoredIndex);
2465  Path = mgr->Read(_T("/file_dialogs/file_new_open/directory"), Path);
2466  }
2467  else
2468  FileFilters::GetFilterIndexFromName(Filters, _("Code::Blocks project/workspace files"), StoredIndex);
2469  }
2470  wxFileDialog dlg(this,
2471  _("Open file"),
2472  Path,
2473  wxEmptyString,
2474  Filters,
2475  wxFD_OPEN | wxFD_MULTIPLE | compatibility::wxHideReadonly);
2476  dlg.SetFilterIndex(StoredIndex);
2477 
2478  PlaceWindow(&dlg);
2479  if (dlg.ShowModal() == wxID_OK)
2480  {
2481  // store the last used filter and directory
2482  // as said : don't do this in case of an 'open project'
2483  if (mgr && !bProject)
2484  {
2485  int Index = dlg.GetFilterIndex();
2486  wxString Filter;
2487  if (FileFilters::GetFilterNameFromIndex(Filters, Index, Filter))
2488  mgr->Write(_T("/file_dialogs/file_new_open/filter"), Filter);
2489  wxString Test = dlg.GetDirectory();
2490  mgr->Write(_T("/file_dialogs/file_new_open/directory"), dlg.GetDirectory());
2491  }
2492  wxArrayString files;
2493  dlg.GetPaths(files);
2494  OnDropFiles(0,0,files);
2495  }
2496 }
2497 
2499 {
2500  DoOnFileOpen(false); // through file menu (not sure if we are opening a project)
2501 }
2502 
2504 {
2505  size_t id = event.GetId() - wxID_CBFILE17;
2506  wxString fname = m_projectsHistory.GetHistoryFile(id);
2507  if (!OpenGeneric(fname, true))
2508  m_projectsHistory.AskToRemoveFileFromHistory(id);
2509 }
2510 
2512 {
2513  m_projectsHistory.ClearHistory();
2514 }
2515 
2517 {
2518  size_t id = event.GetId() - wxID_CBFILE01;
2519  wxString fname = m_filesHistory.GetHistoryFile(id);
2520  if (!OpenGeneric(fname, true))
2521  m_filesHistory.AskToRemoveFileFromHistory(id);
2522 }
2523 
2525 {
2526  m_filesHistory.ClearHistory();
2527 }
2528 
2530 {
2531  if (!Manager::Get()->GetEditorManager()->SaveActive())
2532  {
2533  wxString msg;
2534  msg.Printf(_("File %s could not be saved..."), Manager::Get()->GetEditorManager()->GetActiveEditor()->GetFilename().wx_str());
2535  cbMessageBox(msg, _("Error saving file"), wxICON_ERROR);
2536  }
2537  DoUpdateStatusBar();
2538 }
2539 
2541 {
2543  DoUpdateStatusBar();
2544 }
2545 
2547 {
2548  // no need to call SaveActiveProjectAs(), because this is handled in cbProject::Save()
2549  ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2550  if (prjManager->SaveActiveProject())
2551  m_projectsHistory.AddToHistory(prjManager->GetActiveProject()->GetFilename());
2552  DoUpdateStatusBar();
2553  DoUpdateAppTitle();
2554 }
2555 
2557 {
2558  ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2559  if (prjManager->SaveActiveProjectAs())
2560  m_projectsHistory.AddToHistory(prjManager->GetActiveProject()->GetFilename());
2561  DoUpdateStatusBar();
2562  DoUpdateAppTitle();
2563 }
2564 
2566 {
2567  Manager::Get()->GetConfigManager(_T("app"))->Flush();
2569  ProjectManager *prjManager = Manager::Get()->GetProjectManager();
2570  prjManager->SaveAllProjects();
2571 
2572  if (prjManager->GetWorkspace()->GetModified()
2573  && !prjManager->GetWorkspace()->IsDefault()
2574  && prjManager->SaveWorkspace())
2575  {
2576  m_projectsHistory.AddToHistory(prjManager->GetWorkspace()->GetFilename());
2577  }
2578  DoUpdateStatusBar();
2579  DoUpdateAppTitle();
2580 }
2581 
2583 {
2584  TemplateManager::Get()->SaveUserTemplate(Manager::Get()->GetProjectManager()->GetActiveProject());
2585 }
2586 
2588 {
2589  // we 're not actually shutting down here, but we want to check if the
2590  // active project is still opening files (still busy)
2592  {
2593  wxBell();
2594  return;
2595  }
2597  DoUpdateStatusBar();
2598 }
2599 
2601 {
2602  OpenGeneric(ShowOpenFileDialog(_("Import Dev-C++ project"), FileFilters::GetFilterString(_T('.') + FileFilters::DEVCPP_EXT)), false);
2603 }
2604 
2606 {
2607  OpenGeneric(ShowOpenFileDialog(_("Import MS Visual C++ 6.0 project"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC6_EXT)), false);
2608 }
2609 
2611 {
2612  OpenGeneric(ShowOpenFileDialog(_("Import MS Visual C++ 6.0 workspace"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC6_WORKSPACE_EXT)), false);
2613 }
2614 
2616 {
2617  OpenGeneric(ShowOpenFileDialog(_("Import MS Visual Studio 7.0+ project"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC7_EXT)), false);
2618 }
2619 
2621 {
2622  OpenGeneric(ShowOpenFileDialog(_("Import MS Visual Studio 7.0+ solution"), FileFilters::GetFilterString(_T('.') + FileFilters::MSVC7_WORKSPACE_EXT)), false);
2623 }
2624 
2626 {
2628  if (!pman->GetWorkspace()->IsDefault() && !pman->LoadWorkspace())
2629  {
2630  // do not add the default workspace in recent projects list
2631  // it's always one menu click away
2632  cbMessageBox(_("Can't open default workspace (file exists?)"), _("Warning"), wxICON_WARNING);
2633  }
2634 }
2635 
2637 {
2639  if (pman->SaveWorkspace())
2640  m_projectsHistory.AddToHistory(pman->GetWorkspace()->GetFilename());
2641 }
2642 
2644 {
2646  if (pman->SaveWorkspaceAs(_T("")))
2647  m_projectsHistory.AddToHistory(pman->GetWorkspace()->GetFilename());
2648 }
2649 
2651 {
2652  DoCloseCurrentWorkspace();
2653 }
2654 
2656 {
2658  DoUpdateStatusBar();
2659  Refresh();
2660 }
2661 
2663 {
2665  DoUpdateStatusBar();
2666 }
2667 
2669 {
2671  DoUpdateStatusBar();
2672 }
2673 
2675 {
2677  DoUpdateStatusBar();
2678 }
2679 
2681 {
2682  PrintDialog dlg(this);
2683  PlaceWindow(&dlg);
2684  if (dlg.ShowModal() == wxID_OK)
2686 }
2687 
2689 {
2690  Close(false);
2691 }
2692 
2694 {
2695  // for flicker-free display
2696  event.Skip();
2697 }
2698 
2700 {
2701  // Highlightbutton
2702  if (m_pHighlightButton)
2703  {
2704  wxRect rect;
2705  if ( GetStatusBar()->GetFieldRect(1, rect) )
2706  {
2707  m_pHighlightButton->SetPosition(rect.GetPosition());
2708  m_pHighlightButton->SetSize(rect.GetSize());
2709  }
2710  }
2711 
2712  // for flicker-free display
2713  event.Skip();
2714 }
2715 
2717 {
2718  if (m_InitiatedShutdown)
2719  return;
2720 
2722  Manager::Get()->ProcessEvent(evt);
2723  Manager::Yield();
2724 
2725  m_InitiatedShutdown = true;
2726  Manager::BlockYields(true);
2727 
2728  {
2729  // Check if any compiler plugin is building and ask the user if he/she wants to stop it.
2730  bool hasRunning = cbHasRunningCompilers(Manager::Get()->GetPluginManager());
2731  if (hasRunning)
2732  {
2733  int result = cbMessageBox(_("Currently compiling. Stop compilation and exit?"),
2734  _("Question"), wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION,
2735  this);
2736  if (result == wxID_YES)
2737  cbStopRunningCompilers(Manager::Get()->GetPluginManager());
2738  else
2739  {
2740  event.Veto();
2741  wxBell();
2742  m_InitiatedShutdown = false;
2743  Manager::BlockYields(false);
2744  return;
2745  }
2746  }
2747  }
2748 
2750  {
2751  event.Veto();
2752  wxBell();
2753  m_InitiatedShutdown = false;
2754  Manager::BlockYields(false);
2755  return;
2756  }
2757 
2758  if (!DoCloseCurrentWorkspace())
2759  {
2760  event.Veto();
2761  m_InitiatedShutdown = false;
2762  Manager::BlockYields(false);
2763  return;
2764  }
2765 
2767 
2768  Manager::Get()->GetLogManager()->DebugLog(_T("Deinitializing plugins..."));
2770  Manager::Get()->ProcessEvent(evtShutdown);
2771  Manager::Yield();
2772 
2773  if (!Manager::IsBatchBuild())
2774  SaveWindowState();
2775 
2776  if (m_pPrjManUI->GetNotebook())
2777  m_LayoutManager.DetachPane(m_pPrjManUI->GetNotebook());
2778  m_LayoutManager.DetachPane(m_pInfoPane);
2779  m_LayoutManager.DetachPane(Manager::Get()->GetEditorManager()->GetNotebook());
2780 
2781  m_LayoutManager.UnInit();
2782  TerminateRecentFilesHistory();
2783 
2784  // remove all other event handlers from this window
2785  // this stops it from crashing, when no plugins are loaded
2786  while (GetEventHandler() != this)
2787  PopEventHandler(false);
2788 
2789  // Hide the window
2790  Hide();
2791 
2792  if (!Manager::IsBatchBuild())
2793  {
2794  m_pInfoPane->Destroy();
2795  m_pInfoPane = nullptr;
2796  }
2797 
2798  // Disconnect the mouse right click event handler for toolbars, this should be done before the plugin is
2799  // unloaded in Manager::Shutdown().
2800  PluginToolbarsMap::iterator it;
2801  for( it = m_PluginsTools.begin(); it != m_PluginsTools.end(); ++it )
2802  {
2803  wxToolBar* toolbar = it->second;
2804  if (toolbar)//Disconnect the mouse right click event handler before the toolbar is destroyed
2805  {
2806  bool result = toolbar->Disconnect(wxID_ANY, wxEVT_COMMAND_TOOL_RCLICKED, wxCommandEventHandler(MainFrame::OnToolBarRightClick));
2807  cbAssert(result);
2808  }
2809  }
2810 
2811  Manager::Shutdown(); // Shutdown() is not Free(), Manager is automatically destroyed at exit
2812 
2813  Destroy();
2814 }
2815 
2817 {
2819  DoUpdateStatusBar();
2820 }
2821 
2823 {
2825  if (ed)
2826  ed->GotoMatchingBrace();
2827 }
2828 
2830 {
2832  if (ed && ed->IsBuiltinEditor())
2833  static_cast<cbEditor*>(ed)->ToggleBookmark();
2834 }
2835 
2837 {
2839  if (ed && ed->IsBuiltinEditor())
2840  static_cast<cbEditor*>(ed)->GotoNextBookmark();
2841 }
2842 
2844 {
2846  if (ed && ed->IsBuiltinEditor())
2847  static_cast<cbEditor*>(ed)->GotoPreviousBookmark();
2848 }
2849 
2851 {
2853  if (ed && ed->IsBuiltinEditor())
2854  static_cast<cbEditor*>(ed)->ClearAllBookmarks();
2855 }
2856 
2858 {
2860  if (ed && ed->CanUndo())
2861  {
2863  if (cbEd && cbEd->GetControl()->AutoCompActive())
2864  cbEd->GetControl()->AutoCompCancel();
2865  ed->Undo();
2866  }
2867 }
2868 
2870 {
2872  if (ed)
2873  ed->Redo();
2874 }
2875 
2877 {
2879  if (ed)
2880  ed->ClearHistory();
2881 }
2882 
2884 {
2886  if (ed)
2887  ed->Copy();
2888 }
2889 
2890 void MainFrame::OnEditCut(cb_unused wxCommandEvent& event)
2891 {
2893  if (ed)
2894  ed->Cut();
2895 }
2896 
2898 {
2900  if (ed)
2901  ed->Paste();
2902 }
2903 
2905 {
2907  if (ed)
2908  ed->GetControl()->ParaUp();
2909 }
2910 
2912 {
2914  if (ed)
2915  ed->GetControl()->ParaUpExtend();
2916 }
2917 
2919 {
2921  if (ed)
2922  ed->GetControl()->ParaDown();
2923 }
2924 
2926 {
2928  if (ed)
2929  ed->GetControl()->ParaDownExtend();
2930 }
2931 
2933 {
2935  if (ed)
2936  ed->GetControl()->WordPartLeft();
2937 }
2938 
2940 {
2942  if (ed)
2943  ed->GetControl()->WordPartLeftExtend();
2944 }
2945 
2947 {
2949  if (ed)
2950  ed->GetControl()->WordPartRight();
2951 }
2952 
2954 {
2956  if (ed)
2958 }
2959 
2961 {
2963  if (ed)
2964  ed->GetControl()->ZoomIn();
2965 }
2966 
2968 {
2970  if (ed)
2971  ed->GetControl()->ZoomOut();
2972 }
2973 
2975 {
2977  if (ed)
2978  ed->GetControl()->SetZoom(0);
2979 }
2980 
2982 {
2984  if (ed)
2985  ed->GetControl()->LineCut();
2986 }
2987 
2989 {
2991  if (ed)
2992  ed->GetControl()->LineDelete();
2993 }
2994 
2996 {
2998  if (ed)
2999  ed->GetControl()->LineDuplicate();
3000 }
3001 
3003 {
3005  if (ed)
3006  ed->GetControl()->LineTranspose();
3007 }
3008 
3010 {
3012  if (ed)
3013  ed->GetControl()->LineCopy();
3014 }
3015 
3017 {
3019  if (ed)
3020  {
3021  //We want to undo all in one step
3022  ed->GetControl()->BeginUndoAction();
3023 
3024  int pos = ed->GetControl()->GetCurrentPos();
3025  int line = ed->GetControl()->LineFromPosition(pos);
3026  ed->GetControl()->GotoLine(line);
3027  int column = pos - ed->GetControl()->GetCurrentPos();
3028  ed->GetControl()->Paste();
3029  pos = ed->GetControl()->GetCurrentPos();
3030  ed->GetControl()->GotoPos(pos+column);
3031 
3032  ed->GetControl()->EndUndoAction();
3033  }
3034 }
3035 
3037 {
3039  if (!ed)
3040  return;
3041 
3042  // TODO (mortenmacfly##): Exclude rectangle selection here or not? What behaviour the majority of users expect here???
3043  cbStyledTextCtrl* stc = ed->GetControl();
3044  if (!stc || /*stc->SelectionIsRectangle() ||*/ (stc->GetSelections() > 1))
3045  return;
3046  if (stc->GetLineCount() < 3) // why are you trying to move lines anyways?
3047  return;
3048 
3049  // note that these function calls are a much simpler, however
3050  // they cause text to unnecessarily be marked as modified
3051 // if (event.GetId() == idEditLineUp)
3052 // stc->MoveSelectedLinesUp();
3053 // else
3054 // stc->MoveSelectedLinesDown();
3055 
3056  int startPos = stc->PositionFromLine(stc->LineFromPosition(stc->GetSelectionStart()));
3057  int endPos = stc->LineFromPosition(stc->GetSelectionEnd()); // is line
3058  if ( stc->GetSelectionEnd() == stc->PositionFromLine(endPos) // end is in first column
3059  && stc->PositionFromLine(endPos) != stc->GetLineEndPosition(endPos) // this line has text
3060  && endPos > stc->LineFromPosition(startPos) ) // start and end are on different lines
3061  {
3062  --endPos; // do not unexpectedly select another line
3063  }
3064  const bool isLastLine = (endPos == stc->GetLineCount() - 1);
3065  // warning: stc->GetLineEndPosition(endPos) yields strange results for CR LF (see bug 18892)
3066  endPos = ( isLastLine ? stc->GetLineEndPosition(endPos)
3067  : stc->PositionFromLine(endPos + 1) - 1 ); // is position
3068  if (event.GetId() == idEditLineUp)
3069  {
3070  if (stc->LineFromPosition(startPos) < 1)
3071  return; // cannot move up (we are at the top), exit
3072  stc->BeginUndoAction();
3073  const int offset = (isLastLine ? startPos - stc->GetLineEndPosition(stc->LineFromPosition(startPos) - 1) : 0);
3074  const int lineLength = startPos - stc->PositionFromLine(stc->LineFromPosition(startPos) - 1);
3075  const wxString line = stc->GetTextRange(startPos - lineLength - offset,
3076  startPos - offset);
3077  stc->InsertText(endPos + (isLastLine ? 0 : 1), line);
3078  // warning: line.Length() != lineLength if multibyte characters are used
3079  stc->DeleteRange(startPos - lineLength, lineLength);
3080  startPos -= lineLength;
3081  endPos -= lineLength;
3082  stc->EndUndoAction();
3083  }
3084  else // event.GetId() == idEditLineDown
3085  {
3086  if (isLastLine)
3087  return; // cannot move down (we are at the bottom), exit
3088  stc->BeginUndoAction();
3089  const int lineLength = stc->PositionFromLine(stc->LineFromPosition(endPos + 1) + 1) - endPos - 1;
3090  const wxString line = stc->GetTextRange(endPos + 1,
3091  endPos + 1 + lineLength);
3092  stc->InsertText(startPos, line);
3093  // warning: line.Length() != lineLength if multibyte characters are used
3094  startPos += lineLength;
3095  endPos += lineLength;
3096  stc->DeleteRange(endPos + 1, lineLength);
3097  stc->EndUndoAction();
3098  }
3099  stc->SetSelectionVoid(startPos, endPos);
3100 }
3101 
3103 {
3105  if (ed)
3106  ed->GetControl()->UpperCase();
3107 }
3108 
3110 {
3112  if (ed)
3113  ed->GetControl()->LowerCase();
3114 }
3115 
3117 {
3118  OnEditGotoLineEnd(event);
3120  if (ed)
3121  {
3122  cbStyledTextCtrl* stc = ed->GetControl();
3123  if (stc->AutoCompActive())
3124  stc->AutoCompCancel();
3125  stc->NewLine();
3126  }
3127 }
3128 
3130 {
3132  if (ed)
3133  {
3134  cbStyledTextCtrl* stc = ed->GetControl();
3135  if (stc->AutoCompActive())
3136  stc->AutoCompCancel();
3137  stc->LineEnd();
3138  }
3139 }
3140 
3141 static void InsertNewLine(bool below)
3142 {
3144  if (ed)
3145  {
3146  cbStyledTextCtrl* stc = ed->GetControl();
3147  stc->BeginUndoAction();
3148  if (stc->AutoCompActive())
3149  stc->AutoCompCancel();
3150 
3151  if (below)
3152  {
3153  stc->LineEndDisplay();
3154  int pos = stc->GetCurrentPos();
3155  stc->InsertText(pos, GetEOLStr(stc->GetEOLMode()));
3156  stc->LineDown();
3157  }
3158  else
3159  {
3160  stc->HomeDisplay();
3161  int pos = stc->GetCurrentPos();
3162  stc->InsertText(pos, GetEOLStr(stc->GetEOLMode()));
3163  stc->EndUndoAction();
3164  }
3165  stc->EndUndoAction();
3166  }
3167 }
3168 
3170 {
3171  InsertNewLine(true);
3172 }
3173 
3175 {
3176  InsertNewLine(false);
3177 }
3178 
3180 {
3182  if (eb)
3183  eb->SelectAll();
3184 }
3185 
3186 namespace
3187 {
3188 
3189 struct EditorSelection
3190 {
3191  long caret, anchor;
3192 
3193  bool Empty() const { return caret == anchor; }
3194  bool IsReversed() const { return caret < anchor; }
3195 
3196  long GetStart() const { return std::min(caret, anchor); }
3197  long GetEnd() const { return std::max(caret, anchor); }
3198 
3199  bool Contains(const EditorSelection &selection) const
3200  {
3201  return !(GetEnd() < selection.GetStart() || GetStart() > selection.GetEnd());
3202  }
3203 };
3204 
3205 bool SelectNext(cbStyledTextCtrl *control, const wxString &selectedText, long selectionEnd, bool reversed)
3206 {
3207  // always match case and try to match whole words if they have no special characters
3208  int flag = wxSCI_FIND_MATCHCASE;
3209  if (selectedText.find_first_of(wxT(";:\"'`~@#$%^,-+*/\\=|!?&*(){}[]")) == wxString::npos)
3210  flag |= wxSCI_FIND_WHOLEWORD;
3211 
3212  int endPos = 0; // we need this to work properly with multibyte characters
3213  int eof = control->GetLength();
3214  int pos = control->FindText(selectionEnd, eof, selectedText, flag, &endPos);
3215  if (pos != wxSCI_INVALID_POSITION)
3216  {
3217  control->SetAdditionalSelectionTyping(true);
3218  control->SetMultiPaste(true);
3219  control->IndicatorClearRange(pos, endPos - pos);
3220  if (reversed)
3221  control->AddSelection(pos, endPos);
3222  else
3223  control->AddSelection(endPos, pos);
3224  control->MakeNearbyLinesVisible(control->LineFromPosition(pos));
3225  return true;
3226  }
3227  else
3228  {
3229  InfoWindow::Display(_("Select Next Occurrence"), _("No more available"));
3230  return false;
3231  }
3232 }
3233 
3234 bool GetSelectionInEditor(EditorSelection &selection, cbStyledTextCtrl *control)
3235 {
3236  int main = control->GetMainSelection();
3237  int count = control->GetSelections();
3238  if (main >=0 && main < count)
3239  {
3240  selection.caret = control->GetSelectionNCaret(main);
3241  selection.anchor = control->GetSelectionNAnchor(main);
3242  return true;
3243  }
3244  else
3245  return false;
3246 }
3247 
3248 } // anonymous namespace
3249 
3251 {
3253  if (!eb || !eb->IsBuiltinEditor())
3254  return;
3255  cbStyledTextCtrl *control = static_cast<cbEditor*>(eb)->GetControl();
3256 
3257  EditorSelection selection;
3258  if (!GetSelectionInEditor(selection, control))
3259  return;
3260 
3261  if (!selection.Empty())
3262  {
3263  const wxString &selectedText(control->GetTextRange(selection.GetStart(), selection.GetEnd()));
3264  SelectNext(control, selectedText, selection.GetEnd(), selection.IsReversed());
3265  }
3266  else
3267  {
3268  // Select word at the cursor position if there is nothing selected.
3269  const int start = control->WordStartPosition(selection.caret, true);
3270  const int end = control->WordEndPosition(selection.caret, true);
3271  control->SetSelection(start, end);
3272  }
3273 }
3274 
3276 {
3278  if (!eb || !eb->IsBuiltinEditor())
3279  return;
3280  cbStyledTextCtrl *control = static_cast<cbEditor*>(eb)->GetControl();
3281 
3282  EditorSelection selection;
3283  if (!GetSelectionInEditor(selection, control))
3284  return;
3285 
3286  ConfigManager *cfgEditor = Manager::Get()->GetConfigManager(wxT("editor"));
3287  bool highlightOccurrences = cfgEditor->ReadBool(wxT("/highlight_occurrence/enabled"), true);
3288 
3289  // Select the next occurrence first. This prevents a cursor created at the beginning of the
3290  // file when the user uses the command when there is a single selection. Scintilla always makes
3291  // sure that there is at least one selection/cursor. So if we clear all selections it creates a
3292  // cursor at the beginning of the file.
3293  const wxString &selectedText(control->GetTextRange(selection.GetStart(), selection.GetEnd()));
3294  if (!SelectNext(control, selectedText, selection.GetEnd(), selection.IsReversed()))
3295  return; // If there is no new selection don't deselect the current one.
3296 
3297  // store the selections in a vector except for the current one
3298  typedef std::vector<EditorSelection> Selections;
3299  Selections selections;
3300  int count = control->GetSelections();
3301  for (int ii = 0; ii < count; ++ii)
3302  {
3303  EditorSelection item;
3304  item.caret = control->GetSelectionNCaret(ii);
3305  item.anchor = control->GetSelectionNAnchor(ii);
3306 
3307  if (!item.Contains(selection))
3308  selections.push_back(item);
3309  else if (highlightOccurrences)
3310  {
3311  // Restore the indicator for the highlight occurrences if they are enabled.
3312  control->IndicatorFillRange(item.GetStart(), item.GetEnd());
3313  }
3314  }
3315 
3316  control->ClearSelections();
3317  Selections::const_iterator it = selections.begin();
3318  int index = 0;
3319  if (it != selections.end() && control->GetSelections() > 0)
3320  {
3321  control->SetSelectionNAnchor(index, it->anchor);
3322  control->SetSelectionNCaret(index, it->caret);
3323  ++index;
3324  ++it;
3325  }
3326  for (; it != selections.end(); ++it)
3327  {
3328  control->AddSelection(it->caret, it->anchor);
3329  ++index;
3330  }
3331 }
3332 
3333 /* This is a shameless rip-off of the original OnEditCommentSelected function,
3334  * now more suitingly named OnEditToggleCommentSelected (because that's what
3335  * it does :)
3336  */
3338 {
3340  if (!ed)
3341  return;
3342 
3343  cbStyledTextCtrl* stc = ed->GetControl();
3344  if (!stc)
3345  return;
3346 
3348  if (!colour_set)
3349  return;
3350 
3351  CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3352  if (comment.lineComment==wxEmptyString && comment.streamCommentStart==wxEmptyString)
3353  return;
3354 
3355  stc->BeginUndoAction();
3356  if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3357  {
3358  int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3359  int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3360  int curLine=startLine;
3367  if (startLine != endLine && // selection is more than one line
3368  stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3369  {
3370  // don't take into account the line the caret is on,
3371  // because it contains no selection (caret_column == 0)...
3372  --endLine;
3373  }
3374 
3375  while( curLine <= endLine )
3376  {
3377  // For each line: comment.
3378  if (comment.lineComment!=wxEmptyString)
3379  stc->InsertText( stc->PositionFromLine( curLine ), comment.lineComment );
3380  else // if the language doesn't support line comments use stream comments
3381  {
3382  stc->InsertText( stc->PositionFromLine( curLine ), comment.streamCommentStart );
3383  stc->InsertText( stc->GetLineEndPosition( curLine ), comment.streamCommentEnd );
3384  }
3385  ++curLine;
3386  } // end while
3387  stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3388  }
3389  stc->EndUndoAction();
3390 }
3391 
3392 /* See above (OnEditCommentSelected) for details. */
3394 {
3396  if (!ed)
3397  return;
3398 
3399  cbStyledTextCtrl* stc = ed->GetControl();
3400  if (!stc)
3401  return;
3402 
3404  if (!colour_set)
3405  return;
3406 
3407  CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3408  if (comment.lineComment==wxEmptyString && comment.streamCommentStart==wxEmptyString)
3409  return;
3410 
3411  stc->BeginUndoAction();
3412  if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3413  {
3414  int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3415  int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3416  int curLine = startLine;
3423  if (startLine != endLine && // selection is more than one line
3424  stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3425  {
3426  // don't take into account the line the caret is on,
3427  // because it contains no selection (caret_column == 0)...
3428  --endLine;
3429  }
3430 
3431  while( curLine <= endLine )
3432  {
3433  // For each line: if it is commented, uncomment.
3434  wxString strLine = stc->GetLine( curLine );
3435 
3436  bool startsWithComment;
3437  bool endsWithComment;
3438 
3439  // check for line comment
3440  startsWithComment = strLine.Strip( wxString::leading ).StartsWith( comment.lineComment );
3441  if ( startsWithComment )
3442  { // we know the comment is there (maybe preceded by white space)
3443  int Pos = strLine.Find(comment.lineComment);
3444  int start = stc->PositionFromLine( curLine ) + Pos;
3445  int end = start + comment.lineComment.Length();
3446  stc->SetTargetStart( start );
3447  stc->SetTargetEnd( end );
3448  stc->ReplaceTarget( wxEmptyString );
3449  }
3450 
3451  // check for stream comment
3452  startsWithComment = strLine.Strip( wxString::leading ).StartsWith( comment.streamCommentStart ); // check for stream comment start
3453  endsWithComment = strLine.Strip( wxString::trailing ).EndsWith( comment.streamCommentEnd); // check for stream comment end
3454  if ( startsWithComment && endsWithComment )
3455  {
3456  int Pos;
3457  int start;
3458  int end;
3459 
3460  // we know the start comment is there (maybe preceded by white space)
3461  Pos = strLine.Find(comment.streamCommentStart);
3462  start = stc->PositionFromLine( curLine ) + Pos;
3463  end = start + comment.streamCommentStart.Length();
3464  stc->SetTargetStart( start );
3465  stc->SetTargetEnd( end );
3466  stc->ReplaceTarget( wxEmptyString );
3467 
3468  // we know the end comment is there too (maybe followed by white space)
3469  // attention!! we have to subtract the length of the comment we already removed
3470  Pos = strLine.rfind(comment.streamCommentEnd,strLine.npos) - comment.streamCommentStart.Length();
3471  start = stc->PositionFromLine( curLine ) + Pos;
3472  end = start + comment.streamCommentEnd.Length();
3473  stc->SetTargetStart( start );
3474  stc->SetTargetEnd( end );
3475  stc->ReplaceTarget( wxEmptyString );
3476  }
3477  ++curLine;
3478  } // end while
3479  stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3480  }
3481  stc->EndUndoAction();
3482 }
3483 
3485 {
3487  if (!ed)
3488  return;
3489 
3490  cbStyledTextCtrl* stc = ed->GetControl();
3491  if (!stc)
3492  return;
3493 
3495  if (!colour_set)
3496  return;
3497 
3498  wxString comment = colour_set->GetCommentToken( ed->GetLanguage() ).lineComment;
3499  if (comment==wxEmptyString)
3500  return;
3501 
3502  stc->BeginUndoAction();
3503  if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3504  {
3505  int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3506  int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3507  int curLine = startLine;
3514  if (startLine != endLine && // selection is more than one line
3515  stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3516  {
3517  // don't take into account the line the caret is on,
3518  // because it contains no selection (caret_column == 0)...
3519  --endLine;
3520  }
3521 
3522  bool doComment = false;
3523  while( curLine <= endLine )
3524  {
3525  // Check is any of the selected lines is commented
3526  wxString strLine = stc->GetLine( curLine );
3527  int commentPos = strLine.Strip( wxString::leading ).Find( comment );
3528 
3529  if (commentPos != 0)
3530  {
3531  // At least one line is not commented, so comment the whole selection
3532  // (else if all lines are commented, uncomment the selection)
3533  doComment = true;
3534  break;
3535  }
3536  ++curLine;
3537  }
3538 
3539  curLine = startLine;
3540  while( curLine <= endLine )
3541  {
3542  if (doComment)
3543  stc->InsertText( stc->PositionFromLine( curLine ), comment );
3544  else
3545  {
3546  // we know the comment is there (maybe preceded by white space)
3547  wxString strLine = stc->GetLine( curLine );
3548  int Pos = strLine.Find(comment);
3549  int start = stc->PositionFromLine( curLine ) + Pos;
3550  int end = start + comment.Length();
3551  stc->SetTargetStart( start );
3552  stc->SetTargetEnd( end );
3553  stc->ReplaceTarget( wxEmptyString );
3554  }
3555  ++curLine;
3556  }
3557  stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3558  }
3559  stc->EndUndoAction();
3560 }
3561 
3563 {
3565  if (!ed)
3566  return;
3567 
3568  cbStyledTextCtrl* stc = ed->GetControl();
3569  if (!stc)
3570  return;
3571 
3573  if (!colour_set)
3574  return;
3575 
3576  CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3577  if (comment.streamCommentStart==wxEmptyString)
3578  return;
3579 
3580  stc->BeginUndoAction();
3581  if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3582  {
3583  int startPos = stc->GetSelectionStart();
3584  int endPos = stc->GetSelectionEnd();
3585  if ( startPos == endPos )
3586  { // if nothing selected stream comment current *word* first
3587  startPos = stc->WordStartPosition(stc->GetCurrentPos(), true);
3588  endPos = stc->WordEndPosition (stc->GetCurrentPos(), true);
3589  if ( startPos == endPos )
3590  { // if nothing selected stream comment current *line*
3591  startPos = stc->PositionFromLine (stc->LineFromPosition(startPos));
3592  endPos = stc->GetLineEndPosition(stc->LineFromPosition(startPos));
3593  }
3594  }
3595  else
3596  {
3603  if (stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3604  {
3605  // don't take into account the line the caret is on,
3606  // because it contains no selection (caret_column == 0)...
3607  --endPos;
3608  }
3609  }
3610  // stream comment block
3611  int p1 = startPos - 1;
3612  while (stc->GetCharAt(p1) == _T(' ') && p1 > 0)
3613  --p1;
3614  p1 -= 1;
3615  int p2 = endPos;
3616  while (stc->GetCharAt(p2) == _T(' ') && p2 < stc->GetLength())
3617  ++p2;
3618  const wxString start = stc->GetTextRange(p1, p1 + comment.streamCommentStart.Length());
3619  const wxString end = stc->GetTextRange(p2, p2 + comment.streamCommentEnd.Length());
3620  if (start == comment.streamCommentStart && end == comment.streamCommentEnd)
3621  {
3622  stc->SetTargetStart(p1);
3623  stc->SetTargetEnd(p2 + 2);
3624  wxString target = stc->GetTextRange(p1 + 2, p2);
3625  stc->ReplaceTarget(target);
3626  stc->GotoPos(p1 + target.Length());
3627  }
3628  else
3629  {
3630  stc->InsertText( startPos, comment.streamCommentStart );
3631  // we already inserted some characters so out endPos changed
3632  startPos += comment.streamCommentStart.Length();
3633  endPos += comment.streamCommentStart.Length();
3634  stc->InsertText( endPos, comment.streamCommentEnd );
3635  stc->SetSelectionVoid(startPos,endPos);
3636  }
3637 
3638  }
3639  stc->EndUndoAction();
3640 }
3641 
3643 {
3645  if (!ed)
3646  return;
3647 
3648  cbStyledTextCtrl* stc = ed->GetControl();
3649  if (!stc)
3650  return;
3651 
3653  if (!colour_set)
3654  return;
3655 
3656  CommentToken comment = colour_set->GetCommentToken( ed->GetLanguage() );
3657  if (comment.boxCommentStart==wxEmptyString)
3658  return;
3659 
3660  stc->BeginUndoAction();
3661  if ( wxSCI_INVALID_POSITION != stc->GetSelectionStart() )
3662  {
3663  int startLine = stc->LineFromPosition( stc->GetSelectionStart() );
3664  int endLine = stc->LineFromPosition( stc->GetSelectionEnd() );
3665  int curLine = startLine;
3672  if (startLine != endLine && // selection is more than one line
3673  stc->GetColumn( stc->GetSelectionEnd() ) == 0) // and the caret is at the start of the line
3674  {
3675  // don't take into account the line the caret is on,
3676  // because it contains no selection (caret_column == 0)...
3677  --endLine;
3678  }
3679 
3680 
3681 
3682  if (startLine == endLine) // if selection is only one line ...
3683  {
3684  // ... then insert streamcomment tokens at the beginning and the end of the line
3685  stc->InsertText( stc->PositionFromLine ( curLine ), comment.streamCommentStart );
3686  stc->InsertText( stc->GetLineEndPosition( curLine ), comment.streamCommentEnd );
3687  }
3688  else // selection is more than one line
3689  {
3690  // insert boxcomment start token
3691  stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentStart );
3692  ++curLine; // we already commented the first line about 9 lines above
3693  while( curLine <= endLine )
3694  {
3695  // For each line: comment.
3696  stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentMid );
3697  ++curLine;
3698  } // end while
3699 
3700  // insert boxcomment end token and add a new line character
3701  stc->InsertText( stc->PositionFromLine( curLine ), comment.boxCommentEnd + GetEOLStr(stc->GetEOLMode()) );
3702  } // end if
3703  stc->SetSelectionVoid(stc->PositionFromLine(startLine),stc->PositionFromLine(endLine)+stc->LineLength(endLine));
3704  }
3705  stc->EndUndoAction();
3706 }
3707 
3709 {
3711  Manager::Get()->ProcessEvent(evt);
3712 }
3713 
3715 {
3717  Manager::Get()->ProcessEvent(evt);
3718 }
3719 
3721 {
3723  if (!ed)
3724  return;
3725 
3727  if (!colour_set)
3728  return;
3729 
3730  HighlightLanguage lang = colour_set->GetHighlightLanguage(_T(""));
3731  if (event.GetId() != idEditHighlightModeText)
3732  {
3733  wxMenu* hl = nullptr;
3734  GetMenuBar()->FindItem(idEditHighlightModeText, &hl);
3735  if (hl)
3736  {
3737  wxMenuItem* item = hl->FindItem(event.GetId());
3738  if (item)
3739  lang = colour_set->GetHighlightLanguage(item->GetItemLabelText());
3740  }
3741  }
3742  // Highlightbutton
3743  if (m_pHighlightButton)
3744  changeButtonLabel(*m_pHighlightButton, colour_set->GetLanguageName(lang));
3745  ed->SetLanguage(lang, true);
3747 }
3748 
3750 {
3752  if (ed)
3753  ed->FoldAll();
3754 }
3755 
3757 {
3759  if (ed)
3760  ed->UnfoldAll();
3761 }
3762 
3764 {
3766  if (ed)
3767  ed->ToggleAllFolds();
3768 }
3769 
3771 {
3773  if (ed)
3774  ed->FoldBlockFromLine();
3775 }
3776 
3778 {
3780  if (ed)
3781  ed->UnfoldBlockFromLine();
3782 }
3783 
3785 {
3787  if (ed)
3789 }
3790 
3792 {
3794  if (ed)
3795  {
3796  int mode = -1;
3797 
3798  if (event.GetId() == idEditEOLCRLF)
3799  mode = wxSCI_EOL_CRLF;
3800  else if (event.GetId() == idEditEOLCR)
3801  mode = wxSCI_EOL_CR;
3802  else if (event.GetId() == idEditEOLLF)
3803  mode = wxSCI_EOL_LF;
3804 
3805  if (mode != -1 && mode != ed->GetControl()->GetEOLMode())
3806  {
3807  ed->GetControl()->BeginUndoAction();
3808  ed->GetControl()->ConvertEOLs(mode);
3809  ed->GetControl()->SetEOLMode(mode);
3810  ed->GetControl()->EndUndoAction();
3811  }
3812  }
3813 }
3814 
3816 {
3818  if (!ed)
3819  return;
3820 
3821  if ( event.GetId() == idEditEncodingUseBom )
3822  {
3823  ed->SetUseBom( !ed->GetUseBom() );
3824  return;
3825  }
3826 
3828 
3829  if ( event.GetId() == idEditEncodingDefault )
3830  encoding = wxFONTENCODING_SYSTEM;
3831  else if ( event.GetId() == idEditEncodingAscii )
3832  encoding = wxFONTENCODING_ISO8859_1;
3833  else if ( event.GetId() == idEditEncodingUtf7 )
3834  encoding = wxFONTENCODING_UTF7;
3835  else if ( event.GetId() == idEditEncodingUtf8 )
3836  encoding = wxFONTENCODING_UTF8;
3837  else if ( event.GetId() == idEditEncodingUtf16 )
3838  encoding = wxFONTENCODING_UTF16;
3839  else if ( event.GetId() == idEditEncodingUtf32 )
3840  encoding = wxFONTENCODING_UTF32;
3841  else if ( event.GetId() == idEditEncodingUnicode )
3842  encoding = wxFONTENCODING_UNICODE;
3843  else if ( event.GetId() == idEditEncodingUnicode16BE )
3844  encoding = wxFONTENCODING_UTF16BE;
3845  else if ( event.GetId() == idEditEncodingUnicode16LE )
3846  encoding = wxFONTENCODING_UTF16LE;
3847  else if ( event.GetId() == idEditEncodingUnicode32BE )
3848  encoding = wxFONTENCODING_UTF32BE;
3849  else if ( event.GetId() == idEditEncodingUnicode32LE )
3850  encoding = wxFONTENCODING_UTF32LE;
3851 
3852  ed->SetEncoding(encoding);
3853 }
3854 
3856 {
3857  LoadViewLayout(m_PluginIDsMap[event.GetId()]);
3858 }
3859 
3861 {
3862  wxString def = m_LastLayoutName;
3863  if ( def.empty() )
3864  def = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/main_frame/layout/default"));
3865  wxString name = cbGetTextFromUser(_("Enter the name for this perspective"), _("Save current perspective"), def);
3866  if (!name.IsEmpty())
3867  {
3868  DoFixToolbarsLayout();
3869  SaveViewLayout(name,
3870  m_LayoutManager.SavePerspective(),
3871  m_pInfoPane->SaveTabOrder(),
3872  true);
3873  }
3874 }
3875 
3877 {
3878  if (m_LastLayoutName == gDefaultLayout)
3879  {
3880  if (cbMessageBox(_("The default perspective cannot be deleted. It can always be reverted to "
3881  "a predefined state though.\nDo you want to revert it now?"),
3882  _("Confirmation"),
3884  {
3885  m_LayoutViews[gDefaultLayout] = gDefaultLayoutData;
3886  m_LayoutMessagePane[gDefaultLayout] = gDefaultMessagePaneLayoutData;
3887  LoadViewLayout(gDefaultLayout);
3888  }
3889  return;
3890  }
3891 
3892  if (m_LastLayoutName == gMinimalLayout)
3893  {
3894  if (cbMessageBox(_("The minimal layout cannot be deleted. It can always be reverted to "
3895  "a predefined state though.\nDo you want to revert it now?"),
3896  _("Confirmation"),
3898  {
3899  wxString tempLayout = m_PreviousLayoutName;
3900  m_LayoutViews[gMinimalLayout] = gMinimalLayoutData;
3901  m_LayoutMessagePane[gMinimalLayout] = gMinimalMessagePaneLayoutData;
3902  LoadViewLayout(gMinimalLayout);
3903  m_PreviousLayoutName = tempLayout;
3904  }
3905  return;
3906  }
3907 
3908  if (cbMessageBox(wxString::Format(_("Are you really sure you want to delete the perspective '%s'?"), m_LastLayoutName.wx_str()),
3909  _("Confirmation"),
3911  {
3912  // first delete it from the hashmap
3913  LayoutViewsMap::iterator it = m_LayoutViews.find(m_LastLayoutName);
3914  if (it != m_LayoutViews.end())
3915  m_LayoutViews.erase(it);
3916  it = m_LayoutMessagePane.find(m_LastLayoutName);
3917  if (it != m_LayoutMessagePane.end())
3918  m_LayoutMessagePane.erase(it);
3919 
3920  // now delete the menu item too
3921  wxMenu* viewLayouts = nullptr;
3922  GetMenuBar()->FindItem(idViewLayoutSave, &viewLayouts);
3923  if (viewLayouts)
3924  {
3925  int id = viewLayouts->FindItem(m_LastLayoutName);
3926  if (id != wxNOT_FOUND)
3927  viewLayouts->Delete(id);
3928  // delete the id from the map too
3929  PluginIDsMap::iterator it2 = m_PluginIDsMap.find(id);
3930  if (it2 != m_PluginIDsMap.end())
3931  m_PluginIDsMap.erase(it2);
3932  }
3933 
3934  cbMessageBox(wxString::Format(_("Perspective '%s' deleted.\nWill now revert to perspective '%s'..."), m_LastLayoutName.wx_str(), gDefaultLayout.wx_str()),
3935  _("Information"), wxICON_INFORMATION);
3936 
3937  // finally, revert to the default layout
3938  m_LastLayoutName = gDefaultLayout; // do not ask to save old layout ;)
3939  LoadViewLayout(gDefaultLayout);
3940  }
3941 }
3942 
3944 {
3945  if (m_LastLayoutName == gMinimalLayout)
3946  LoadViewLayout(m_PreviousLayoutName.IsEmpty()?Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/environment/view/layout_to_toggle"),gDefaultLayout):m_PreviousLayoutName);
3947  else
3948  {
3949  ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("app"));
3950  if (cfg->ReadBool(_T("/environment/view/dbl_clk_maximize"), true))
3951  LoadViewLayout(gMinimalLayout);
3952  }
3953 }
3954 
3956 {
3957  ShowHideScriptConsole();
3958 }
3959 
3961 {
3963  if (nb)
3964  {
3965  bool hide_editor_tabs = nb->GetTabCtrlHeight() > 0;
3966 
3967  if (hide_editor_tabs)
3968  nb->SetTabCtrlHeight(0);
3969  else
3970  nb->SetTabCtrlHeight(-1);
3971 
3972  Manager::Get()->GetConfigManager(_T("app"))->Write(_T("/environment/hide_editor_tabs"), hide_editor_tabs);
3973  }
3974 }
3975 
3977 {
3978  bool bDoMultipleFiles = (event.GetId() == idSearchFindInFiles);
3979  if (!bDoMultipleFiles)
3980  bDoMultipleFiles = !Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
3981  m_findReplace.ShowFindDialog(false, bDoMultipleFiles);
3982 }
3983 
3985 {
3986  bool bNext = !(event.GetId() == idSearchFindPrevious);
3987  m_findReplace.FindNext(bNext, nullptr, nullptr, false);
3988 }
3989 
3991 {
3992  bool bNext = !(event.GetId() == idSearchFindSelectedPrevious);
3993  m_findReplace.FindSelectedText(bNext);
3994 }
3995 
3997 {
3998  bool bDoMultipleFiles = (event.GetId() == idSearchReplaceInFiles);
3999  if (!bDoMultipleFiles)
4000  bDoMultipleFiles = !Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
4001  m_findReplace.ShowFindDialog(true, bDoMultipleFiles);
4002 }
4003 
4005 {
4007  if (!ed)
4008  return;
4009 
4010  int max = ed->GetControl()->LineFromPosition(ed->GetControl()->GetLength()) + 1;
4011 
4019  wxString strLine = cbGetTextFromUser( wxString::Format(_("Line (1 - %d): "), max),
4020  _("Goto line"),
4021  _T( "" ),
4022  this );
4023  long int line = 0;
4024  strLine.ToLong(&line);
4025  if ( line >= 1 && line <= max )
4026  {
4027  ed->UnfoldBlockFromLine(line - 1);
4028  ed->GotoLine(line - 1);
4029  }
4030 }
4031 
4033 {
4035  if (ed)
4036  ed->GotoNextChanged();
4037 }
4038 
4040 {
4042  if (ed)
4043  ed->GotoPreviousChanged();
4044 }
4045 
4047 {
4048  dlgAbout dlg(this);
4049  PlaceWindow(&dlg, pdlHead);
4050  dlg.ShowModal();
4051 }
4052 
4054 {
4055  ShowTips(true);
4056 }
4057 
4059 {
4061  {
4062  event.Skip();
4063  return;
4064  }
4065 
4067  {
4068  event.Enable(false);
4069  return;
4070  }
4071 
4072  EditorManager *editorManager = Manager::Get()->GetEditorManager();
4073  EditorBase *ed = (editorManager ? editorManager->GetActiveEditor() : nullptr);
4074  EditorBase *sh = (editorManager ? editorManager->GetEditor(g_StartHereTitle) : nullptr);
4075 
4076  const int id = event.GetId();
4077 
4078  // Single file related menu items
4079  if (id == idFileClose || id == idFileCloseAll || id == idFileSaveAs)
4080  event.Enable(ed && ed != sh);
4081  else if (id == idFileSave)
4082  event.Enable(ed && ed->GetModified());
4083  else if (id == idFilePrint)
4084  event.Enable(editorManager && editorManager->GetBuiltinActiveEditor());
4085  else if (id == idFileOpen)
4086  event.Enable(true);
4087  else
4088  {
4089  ProjectManager *projectManager = Manager::Get()->GetProjectManager();
4090  cbProject *project = (projectManager ? projectManager->GetActiveProject() : nullptr);
4091  if (project && project->GetCurrentlyCompilingTarget())
4092  {
4093  event.Enable(false);
4094  return;
4095  }
4096 
4097  // Project related menu items
4098  if (id == idFileReopenProject)
4099  event.Enable(true);
4100  else if (id == idFileCloseProject || id == idFileSaveProjectAs || id == idFileSaveProjectTemplate)
4101  event.Enable(project != nullptr);
4102  else if (id == idFileSaveProject)
4103  event.Enable(project && project->GetModified());
4104  else if (id == idFileOpenDefWorkspace || id == idFileSaveWorkspaceAs || id == idFileSaveAll)
4105  event.Enable(true);
4106  else
4107  {
4108  // Workspace related menu items
4109  const cbWorkspace *workspace = Manager::Get()->GetProjectManager()->GetWorkspace();
4110 
4111  if (id == idFileSaveWorkspace)
4112  event.Enable(workspace && workspace->GetModified());
4113  else if (id == idFileCloseWorkspace)
4114  event.Enable(workspace != nullptr);
4115  else
4116  event.Skip();
4117  }
4118  }
4119 }
4120 
4122 {
4124  {
4125  event.Skip();
4126  return;
4127  }
4128 
4129  cbEditor* ed = NULL;
4130  EditorBase* eb = NULL;
4131  bool hasSel = false;
4132  bool canUndo = false;
4133  bool canRedo = false;
4134  bool canPaste = false;
4135  bool canCut = false;
4136  bool canSelAll = false;
4137 
4138  if (Manager::Get()->GetEditorManager() && !Manager::IsAppShuttingDown())
4139  {
4142  }
4143 
4144  wxMenuBar* mbar = GetMenuBar();
4145 
4146  if (eb)
4147  {
4148  canUndo = eb->CanUndo();
4149  canRedo = eb->CanRedo();
4150  hasSel = eb->HasSelection();
4151  canPaste = eb->CanPaste();
4152  canCut = !eb->IsReadOnly() && hasSel;
4153  canSelAll = eb->CanSelectAll();
4154  }
4155 
4156  mbar->Enable(idEditUndo, canUndo);
4157  mbar->Enable(idEditRedo, canRedo);
4158  mbar->Enable(idEditClearHistory, canUndo || canRedo);
4159  mbar->Enable(idEditCut, canCut);
4160  mbar->Enable(idEditCopy, hasSel);
4161  mbar->Enable(idEditPaste, canPaste);
4162  mbar->Enable(idEditSwapHeaderSource, ed);
4163  mbar->Enable(idEditGotoMatchingBrace, ed);
4164  mbar->Enable(idEditHighlightMode, ed);
4165  mbar->Enable(idEditSelectAll, canSelAll);
4166  mbar->Enable(idEditSelectNext, ed);
4167  mbar->Enable(idEditSelectNextSkip, hasSel);
4168  mbar->Enable(idEditBookmarks, ed);
4169  mbar->Enable(idEditFolding, ed &&
4170  Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/folding/show_folds"), false));
4171  mbar->Enable(idEditEOLMode, ed);
4172  mbar->Enable(idEditEncoding, ed);
4173  mbar->Enable(idEditSpecialCommands, ed);
4174  mbar->Enable(idEditSpecialCommandsCase, ed && hasSel);
4175  mbar->Enable(idEditCommentSelected, ed);
4176  mbar->Enable(idEditUncommentSelected, ed);
4177  mbar->Enable(idEditToggleCommentSelected, ed);
4178  mbar->Enable(idEditStreamCommentSelected, ed);
4179  mbar->Enable(idEditBoxCommentSelected, ed);
4180  mbar->Enable(idEditShowCallTip, ed);
4181  mbar->Enable(idEditCompleteCode, ed);
4182 
4183  if (ed)
4184  {
4185  // OK... this was the strangest/silliest/most-frustrating bug ever in the computer programs history...
4186  // Under wxGTK it seems that if you try to Check() a menu item if its container Menu is disabled,
4187  // you enter an endless message loop eating 100% CPU...
4188  // DARN!
4189  // This fixes the dreaded 'linux-hang-on-close-project' bug.
4190 
4191  switch (ed->GetControl()->GetEOLMode())
4192  {
4193  case wxSCI_EOL_CRLF:
4194  mbar->Check(idEditEOLCRLF, true);
4195  break;
4196  case wxSCI_EOL_CR:
4197  mbar->Check(idEditEOLCR, true);
4198  break;
4199  case wxSCI_EOL_LF:
4200  mbar->Check(idEditEOLLF, true);
4201  break;
4202  default:
4203  (platform::windows ? mbar->Check(idEditEOLCRLF, true) : mbar->Check(idEditEOLLF, true));
4204  break;
4205  }
4206 
4207  bool defenc = ed && ( ed->GetEncoding() == wxFONTENCODING_SYSTEM
4208  || ed->GetEncoding() == wxLocale::GetSystemEncoding() );
4209 
4210  mbar->Check(idEditEncodingDefault, defenc);
4211  mbar->Check(idEditEncodingUseBom, ed && ed->GetUseBom());
4212  mbar->Check(idEditEncodingAscii, ed && ed->GetEncoding() == wxFONTENCODING_ISO8859_1);
4213  mbar->Check(idEditEncodingUtf7, ed && ed->GetEncoding() == wxFONTENCODING_UTF7);
4214  mbar->Check(idEditEncodingUtf8, ed && ed->GetEncoding() == wxFONTENCODING_UTF8);
4215  mbar->Check(idEditEncodingUnicode, ed && ed->GetEncoding() == wxFONTENCODING_UNICODE);
4216  mbar->Check(idEditEncodingUtf16, ed && ed->GetEncoding() == wxFONTENCODING_UTF16);
4217  mbar->Check(idEditEncodingUtf32, ed && ed->GetEncoding() == wxFONTENCODING_UTF32);
4218  mbar->Check(idEditEncodingUnicode16BE, ed && ed->GetEncoding() == wxFONTENCODING_UTF16BE);
4219  mbar->Check(idEditEncodingUnicode16LE, ed && ed->GetEncoding() == wxFONTENCODING_UTF16LE);
4220  mbar->Check(idEditEncodingUnicode32BE, ed && ed->GetEncoding() == wxFONTENCODING_UTF32BE);
4221  mbar->Check(idEditEncodingUnicode32LE, ed && ed->GetEncoding() == wxFONTENCODING_UTF32LE);
4222 
4223  wxMenu* hl = nullptr;
4224  mbar->FindItem(idEditHighlightModeText, &hl);
4225  if (hl)
4226  {
4227  EditorColourSet* colour_set = ed->GetColourSet();
4228  if (colour_set)
4229  {
4230  int item = hl->FindItem(colour_set->GetLanguageName(ed->GetLanguage()));
4231  if (item != wxNOT_FOUND)
4232  mbar->Check(item, true);
4233  }
4234  }
4235  }
4236 
4237  if (m_pToolbar)
4238  {
4239  m_pToolbar->EnableTool(idEditUndo, canUndo);
4240  m_pToolbar->EnableTool(idEditRedo, canRedo);
4241  m_pToolbar->EnableTool(idEditCut, canCut);
4242  m_pToolbar->EnableTool(idEditCopy, hasSel);
4243  m_pToolbar->EnableTool(idEditPaste, canPaste);
4244  }
4245 
4246  event.Skip();
4247 }
4248 
4250 {
4252  {
4253  event.Skip();
4254  return;
4255  }
4256 
4257  wxMenuBar* mbar = GetMenuBar();
4259  bool manVis = m_LayoutManager.GetPane(m_pPrjManUI->GetNotebook()).IsShown();
4260 
4261  mbar->Check(idViewManager, manVis);
4262  mbar->Check(idViewLogManager, m_LayoutManager.GetPane(m_pInfoPane).IsShown());
4263  mbar->Check(idViewStartPage, Manager::Get()->GetEditorManager()->GetEditor(g_StartHereTitle)!=NULL);
4264  mbar->Check(idViewStatusbar, GetStatusBar() && GetStatusBar()->IsShown());
4265  mbar->Check(idViewScriptConsole, m_LayoutManager.GetPane(m_pScriptConsole).IsShown());
4266  mbar->Check(idViewHideEditorTabs, Manager::Get()->GetEditorManager()->GetNotebook()->GetTabCtrlHeight() == 0);
4267  mbar->Check(idViewFullScreen, IsFullScreen());
4268  mbar->Enable(idViewFocusEditor, ed);
4269  mbar->Enable(idViewFocusManagement, manVis);
4270  mbar->Enable(idViewFocusLogsAndOthers, m_pInfoPane->IsShown());
4271 
4272  // toolbars
4273  wxMenu* viewToolbars = nullptr;
4274  GetMenuBar()->FindItem(idViewToolMain, &viewToolbars);
4275  if (viewToolbars)
4276  {
4277  SetChecksForViewToolbarsMenu(*viewToolbars);
4278  }
4279 
4280  event.Skip();
4281 }
4282 
4284 {
4286  {
4287  event.Skip();
4288  return;
4289  }
4290 
4293  Manager::Get()->GetEditorManager()->GetActiveEditor() ) : nullptr;
4294 
4295  bool enableGoto = false;
4296  if (ed)
4297  enableGoto = Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true)
4298  && (ed->CanUndo() || ed->CanRedo());
4299 
4300  wxMenuBar* mbar = GetMenuBar();
4301 
4302  // 'Find' and 'Replace' are always enabled for (find|replace)-in-files
4303  // (idSearchFindInFiles and idSearchReplaceInFiles)
4304 
4305  mbar->Enable(idSearchFind, ed);
4306  mbar->Enable(idSearchFindNext, ed);
4307  mbar->Enable(idSearchFindPrevious, ed);
4308  mbar->Enable(idSearchFindSelectedNext, ed);
4309  mbar->Enable(idSearchFindSelectedPrevious, ed);
4310  mbar->Enable(idSearchReplace, ed);
4311  mbar->Enable(idSearchGotoLine, ed);
4312  mbar->Enable(idSearchGotoNextChanged, enableGoto);
4313  mbar->Enable(idSearchGotoPreviousChanged, enableGoto);
4314 
4315  event.Skip();
4316 }
4317 
4318 
4320 {
4322  {
4323  event.Skip();
4324  return;
4325  }
4326 
4327  if (Manager::Get()->GetEditorManager() && event.GetEditor() == Manager::Get()->GetEditorManager()->GetActiveEditor())
4328  {
4329 #if wxCHECK_VERSION(3, 0, 0)
4330  // Execute the code to update the status bar outside of the paint event for scintilla.
4331  // Executing this function directly in the event handler causes redraw problems on Windows.
4332  CallAfter(&MainFrame::DoUpdateStatusBar);
4333 #else
4334  DoUpdateStatusBar();
4335 #endif // defined(__wxMSW__) && wxCHECK_VERSION(3, 0, 0)
4336  }
4337 
4338  event.Skip();
4339 }
4340 
4341 namespace
4342 {
4343 struct ToolbarFitInfo
4344 {
4345  int row;
4346  wxRect rect;
4347  wxWindow *window;
4348 
4349  bool operator<(const ToolbarFitInfo &r) const
4350  {
4351  if (row < r.row)
4352  return true;
4353  else if (row == r.row)
4354  return rect.x < r.rect.x;
4355  else
4356  return false;
4357  }
4358 };
4359 
4360 static void CollectToolbars(std::set<ToolbarFitInfo> &result, wxAuiManager &layoutManager)
4361 {
4362  const wxAuiPaneInfoArray &panes = layoutManager.GetAllPanes();
4363  for (size_t ii = 0; ii < panes.GetCount(); ++ii)
4364  {
4365  const wxAuiPaneInfo &info = panes[ii];
4366  if (info.IsToolbar() && info.IsShown())
4367  {
4368  ToolbarFitInfo f;
4369  f.row = info.dock_row;
4370  f.rect = info.rect;
4371  f.window = info.window;
4372  result.insert(f);
4373  }
4374  }
4375 }
4376 
4377 struct ToolbarRowInfo
4378 {
4379  ToolbarRowInfo() {}
4380  ToolbarRowInfo(int width_, int position_) : width(width_), position(position_) {}
4381 
4382  int width, position;
4383 };
4384 
4385 // Function which tries to make all toolbars visible.
4386 static void FitToolbars(wxAuiManager &layoutManager, wxWindow *mainFrame)
4387 {
4388  std::set<ToolbarFitInfo> sorted;
4389  CollectToolbars(sorted, layoutManager);
4390  if (sorted.empty())
4391  return;
4392 
4393  int maxWidth = mainFrame->GetSize().x;
4394  int gripperSize = layoutManager.GetArtProvider()->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
4395 
4396  // move all toolbars to the left as possible and add the non-fitting to a list
4397  std::vector<ToolbarRowInfo> rows;
4398  std::vector<wxWindow*> nonFitingToolbars;
4399  for (std::set<ToolbarFitInfo>::const_iterator it = sorted.begin(); it != sorted.end(); ++it)
4400  {
4401  wxAuiPaneInfo &pane = layoutManager.GetPane(it->window);
4402  int row = pane.dock_row;
4403  while (static_cast<int>(rows.size()) <= row)
4404  rows.push_back(ToolbarRowInfo(0, 0));
4405 
4406  int maxX = rows[row].width + it->window->GetBestSize().x + gripperSize;
4407  if (maxX > maxWidth)
4408  nonFitingToolbars.push_back(it->window);
4409  else
4410  {
4411  rows[row].width = maxX;
4412  pane.Position(rows[row].position++);
4413  }
4414  }
4415 
4416  // move the non-fitting toolbars at the bottom
4417  int lastRow = rows.empty() ? 0 : (rows.size() - 1);
4418  int position = rows.back().position, maxX = rows.back().width;
4419  for (std::vector<wxWindow*>::iterator it = nonFitingToolbars.begin(); it != nonFitingToolbars.end(); ++it)
4420  {
4421  maxX += (*it)->GetBestSize().x;
4422  maxX += gripperSize;
4423  if (maxX > maxWidth)
4424  {
4425  position = 0;
4426  lastRow++;
4427  maxX = (*it)->GetBestSize().x + gripperSize;
4428  }
4429  layoutManager.GetPane(*it).Position(position++).Row(lastRow);
4430  }
4431 }
4432 
4433 // Function which tries to minimize the space used by the toolbars.
4434 // Also it can be used to show toolbars which have gone outside the window.
4435 static void OptimizeToolbars(wxAuiManager &layoutManager, wxWindow *mainFrame)
4436 {
4437  std::set<ToolbarFitInfo> sorted;
4438  CollectToolbars(sorted, layoutManager);
4439  if (sorted.empty())
4440  return;
4441 
4442  int maxWidth = mainFrame->GetSize().x;
4443  int lastRow = 0, position = 0, maxX = 0;
4444  int gripperSize = layoutManager.GetArtProvider()->GetMetric(wxAUI_DOCKART_GRIPPER_SIZE);
4445 
4446  for (std::set<ToolbarFitInfo>::const_iterator it = sorted.begin(); it != sorted.end(); ++it)
4447  {
4448  maxX += it->window->GetBestSize().x;
4449  maxX += gripperSize;
4450  if (maxX > maxWidth)
4451  {
4452  position = 0;
4453  lastRow++;
4454  maxX = it->window->GetBestSize().x + gripperSize;
4455  }
4456  layoutManager.GetPane(it->window).Position(position++).Row(lastRow);
4457  }
4458 }
4459 
4460 } // anomymous namespace
4461 
4463 {
4464  FitToolbars(m_LayoutManager, this);
4465  DoUpdateLayout();
4466 }
4467 
4469 {
4470  OptimizeToolbars(m_LayoutManager, this);
4471  DoUpdateLayout();
4472 }
4473 
4475 {
4476  wxWindow* win = nullptr;
4477  bool toolbar = false;
4478  if (event.GetId() == idViewManager)
4479  win = m_pPrjManUI->GetNotebook();
4480  else if (event.GetId() == idViewLogManager)
4481  win = m_pInfoPane;
4482  else if (event.GetId() == idViewToolMain)
4483  {
4484  win = m_pToolbar;
4485  toolbar = true;
4486  }
4487  else if (event.GetId() == idViewToolDebugger)
4488  {
4489  win = m_debuggerToolbarHandler->GetToolbar();
4490  toolbar = true;
4491  }
4492  else
4493  {
4494  wxString pluginName = m_PluginIDsMap[event.GetId()];
4495  if (!pluginName.IsEmpty())
4496  {
4497  cbPlugin* plugin = Manager::Get()->GetPluginManager()->FindPluginByName(pluginName);
4498  if (plugin)
4499  {
4500  win = m_PluginsTools[plugin];
4501  toolbar = true;
4502  }
4503  }
4504  }
4505 
4506  if (win)
4507  {
4508  // use last visible size as BestSize, Logs & others does no longer "forget" it's size
4509  if (!event.IsChecked())
4510  m_LayoutManager.GetPane(win).BestSize(win->GetSize());
4511 
4512  m_LayoutManager.GetPane(win).Show(event.IsChecked());
4513  if (toolbar)
4514  FitToolbars(m_LayoutManager, this);
4515  DoUpdateLayout();
4516  }
4517 }
4518 
4520 {
4521  cbStatusBar* sb = (cbStatusBar*)GetStatusBar();
4522  if (!sb) return;
4523 
4524  ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("app"));
4525  const bool show = !cfg->ReadBool(_T("/main_frame/statusbar"), true);
4526  cfg->Write(_T("/main_frame/statusbar"), show);
4527 
4528  DoUpdateStatusBar();
4529  sb->Show(show);
4530  if ( show ) SendSizeEvent();
4531  DoUpdateLayout();
4532 }
4533 
4535 {
4537  cbAuiNotebook* nb = edman?edman->GetNotebook():nullptr;
4538  if (nb)
4539  nb->FocusActiveTabCtrl();
4540 }
4541 
4543 {
4544  cbAuiNotebook* nb = m_pPrjManUI ? m_pPrjManUI->GetNotebook() : nullptr;
4545  if (nb)
4546  nb->FocusActiveTabCtrl();
4547 }
4548 
4550 {
4551  if (m_pInfoPane)
4552  m_pInfoPane->FocusActiveTabCtrl();
4553 }
4554 
4556 {
4557  // Get the notebook from the editormanager:
4559  if (!nb)
4560  return<