1 #include "ide.h"
2
3 #define KEYGROUPNAME "Ide"
4 #define KEYNAMESPACE IdeKeys
5 #define KEYFILE <ide/ide.key>
6 #include <CtrlLib/key_source.h>
7
8 using namespace IdeKeys;
9
DoEditKeys()10 void Ide::DoEditKeys()
11 {
12 EditKeys();
13 AKEditor();
14 }
15
AKEditor()16 void Ide::AKEditor()
17 {
18 CodeEditor::find_next_key = AK_FINDNEXT().key[0];
19 CodeEditor::find_prev_key = AK_FINDPREV().key[0];
20 CodeEditor::replace_key = AK_DOREPLACE().key[0];
21 }
22
PackageMenu(Bar & menu)23 void Ide::PackageMenu(Bar& menu)
24 {
25 Project(menu);
26 }
27
FileBookmark(Bar & menu)28 void Ide::FileBookmark(Bar& menu)
29 {
30 int i;
31 for(i = 0; i < 10; i++) {
32 const Bookmark& b = bookmark[i];
33 String txt = Format("Goto bookmark &%d", i);
34 if(!b.file.IsEmpty())
35 txt << " (" << bookmark[i].file << ')';
36 menu.Add(!b.file.IsEmpty(), txt, THISBACK1(BookKey, K_CTRL_0 + i))
37 .Key(K_CTRL_0 + i);
38 }
39 menu.MenuBreak();
40 for(i = 0; i < 10; i++)
41 menu.Add("Set", THISBACK1(BookKey, K_SHIFT_CTRL_0 + i))
42 .Key(K_SHIFT_CTRL_0 + i);
43 }
44
File(Bar & menu)45 void Ide::File(Bar& menu)
46 {
47 if (!IsEditorMode())
48 {
49 menu.Add(AK_SETMAIN, IdeImg::MainPackage(), THISBACK(NewMainPackage))
50 .Enable(!IdeIsDebugLock())
51 .Help("Select global configuration (var), select / add main project package");
52 }
53
54 menu.AddMenu(AK_EDITFILE, CtrlImg::open(), THISBACK(EditAnyFile))
55 .Help("Select any file in file selector and open it in editor");
56 menu.AddMenu(!IsNull(GetOpposite()), AK_OPPOSITE, IdeImg::opposite(), THISBACK(GoOpposite))
57 .Help("Switch between source and header file");
58 menu.AddMenu(AK_SAVEFILE, CtrlImg::save(), THISBACK(DoSaveFile))
59 .Help("Save current file");
60 if(!designer)
61 menu.AddMenu(CanToggleReadOnly(), AK_READONLY, IdeImg::read_only(), THISBACK(ToggleReadOnly))
62 .Check(editor.IsReadOnly())
63 .Help("Set / clear read-only flag for current file");
64
65 menu.AddMenu(!designer, AK_PRINT, CtrlImg::print(), THISBACK(Print));
66
67 // menu.Add("Export project", THISBACK(ExportProject))
68 // .Help("Copy all project files into given directory");
69
70 if(menu.IsMenuBar())
71 {
72 menu.Separator();
73 menu.Add(AK_CLOSETAB, THISBACK(ClearTab))
74 .Help("Close the current file tab");
75 menu.Add(AK_CLOSETABS, THISBACK(ClearTabs))
76 .Help("Close all file tabs");
77 if(!designer) {
78 menu.Add("Bookmarks", THISBACK(FileBookmark))
79 .Help("Set one of available bookmarks (1..9, 0) on current file");
80 menu.MenuSeparator();
81 }
82 menu.Add("Show/hide bottom pane", THISBACK(SwapBottom))
83 .Check(IsBottomShown())
84 .Key(K_ESCAPE)
85 .Help("Show / hide bottom pane (with console, calc and browser tabs)");
86 }
87
88 menu.Add(AK_PACKAGESFILES, THISBACK(SwapPackagesFiles))
89 .Check(weframe.IsShown());
90
91 menu.MenuSeparator();
92
93 bool split = editorsplit.GetZoom() < 0;
94 menu.Add(AK_SPLIT, THISBACK1(KeySplit, false))
95 .Check(split && editorsplit.IsVert());
96 menu.Add(AK_VSPLIT, THISBACK1(KeySplit, true))
97 .Check(split && editorsplit.IsHorz());
98 menu.Add(split, AK_SWAP, THISBACK(SwapEditors));
99
100 menu.MenuSeparator();
101
102 menu.Add(AK_OPENFILEDIR, THISBACK(OpenFileFolder));
103 menu.MenuSeparator();
104
105 menu.Add(AK_STATISTICS, THISBACK(Statistics))
106 .Help("Display various statistics");
107
108 menu.Add("Project licences..", THISBACK(Licenses));
109 menu.Add("Elapsed times..", THISBACK(Times));
110
111 menu.Add(AK_EXIT, THISBACK(Exit));
112 }
113
OnlineSearchMenu(Bar & menu)114 void Ide::OnlineSearchMenu(Bar& menu)
115 {
116 bool b = editor.IsSelection() || IsAlNum(editor.GetChar()) || editor.GetChar() == '_';
117 menu.Add(b, AK_GOOGLE, IdeImg::Google(),
118 THISBACK(OnlineSearch));
119 menu.Add(b, AK_GOOGLEUPP, IdeImg::GoogleUpp(), THISBACK(OnlineSearchOnTheOfficialSite));
120 }
121
AssistEdit(Bar & menu)122 void Ide::AssistEdit(Bar& menu)
123 {
124 bool b = !editor.IsReadOnly() && !designer;
125 menu.Add(b, "Insert", THISBACK(InsertMenu));
126 menu.Add(b, "Insert #include", THISBACK(InsertInclude));
127 }
128
InsertAdvanced(Bar & bar)129 void Ide::InsertAdvanced(Bar& bar)
130 {
131 bool b = !editor.IsReadOnly();
132 AssistEdit(bar);
133 bar.Add(b, "Advanced", THISBACK(EditSpecial));
134 }
135
EditSpecial(Bar & menu)136 void Ide::EditSpecial(Bar& menu)
137 {
138 bool b = !editor.IsReadOnly();
139 menu.Add(AK_WORDWRAP, THISBACK(ToggleWordwrap))
140 .Check(wordwrap);
141
142 menu.Separator();
143
144 menu.Add(b, AK_SPACESTOTABS, THISBACK(EditMakeTabs))
145 .Help("Convert leading blanks on each line to tabs");
146 menu.Add(b, AK_TABSTOSPACES, THISBACK(EditMakeSpaces))
147 .Help("Convert all tabs to spaces");
148 menu.Add(b, AK_LINEENDINGS, THISBACK(EditMakeLineEnds))
149 .Help("Remove tabs and spaces at line endings");
150 menu.Add(b, AK_TRANSLATESTRING, THISBACK(TranslateString))
151 .Help("Mark the current selection as translated string");
152 menu.Add(b, AK_SWAPCHARS, THISBACK(SwapChars))
153 .Help("Transpose characters");
154 menu.Add(AK_COPYWORD, THISBACK(CopyWord))
155 .Help("Copy the current identifier to the clipboard");
156 menu.Add(b, AK_DUPLICATELINE, THISBACK(DuplicateLine))
157 .Help("Duplicate the current line");
158 menu.Add(b, AK_FORMATCODE, THISBACK(FormatCode))
159 .Help("Reformat code in editor");
160 menu.Add(b && editor.IsSelection(), AK_TOUPPER, THISBACK(TextToUpper))
161 .Help("Convert letters in selection to uppercase");
162 menu.Add(b && editor.IsSelection(), AK_TOLOWER, THISBACK(TextToLower))
163 .Help("Convert letters in selection to lowercase");
164 menu.Add(b && editor.IsSelection(), AK_TOASCII, THISBACK(TextToAscii))
165 .Help("Covert text to 7-bit ASCII removing all accents and special symbols");
166 menu.Add(b && editor.IsSelection(), AK_INITCAPS, THISBACK(TextInitCaps))
167 .Help("Capitalize the first character of words in selection");
168 menu.Add(b && editor.IsSelection(), AK_SWAPCASE, THISBACK(SwapCase))
169 .Help("Swap the case of letters in selection");
170 menu.Add(b && editor.IsSelection(), AK_TOCSTRING, THISBACK(ToCString))
171 .Help("Convert selection to CString");
172 menu.Add(b && editor.IsSelection(), AK_TOCOMMENT, THISBACK(ToComment))
173 .Help("Comment code");
174 menu.Add(b && editor.IsSelection(), AK_COMMENTLINES, THISBACK(CommentLines))
175 .Help("Comment code lines");
176 menu.Add(b && editor.IsSelection(), AK_UNCOMMENT, THISBACK(UnComment))
177 .Help("Uncomment code");
178 menu.Add(b, AK_REFORMAT_COMMENT, THISBACK(ReformatComment))
179 .Help("Reformat multiline comment into paragraph");
180 menu.Add(b, "Remove debugging logs (DDUMP...)", [=] { RemoveDs(); });
181 }
182
SearchMenu(Bar & menu)183 void Ide::SearchMenu(Bar& menu)
184 {
185 if(!designer) {
186 menu.Add(AK_FIND, THISBACK(EditFind))
187 .Help("Search for text or text pattern");
188 menu.Add(!editor.IsReadOnly(), AK_REPLACE, THISBACK(EditReplace))
189 .Help("Search for text or text pattern, with replace option");
190 // menu.Add(AK_FINDSEL, THISBACK(EditFindReplacePickText))
191 // .Help("Show find / replace dialog & set active text as the 'find' text");
192
193 menu.Add(AK_FINDNEXT, THISBACK(EditFindNext))
194 .Help("Find next occurrence");
195 menu.Add(AK_FINDPREV, THISBACK(EditFindPrevious))
196 .Help("Find previous occurrence");
197
198 menu.MenuSeparator();
199
200 menu.Add(AK_FINDSTRING, THISBACK1(FindString, false))
201 .Help("Find any ordinary string constant (\"\" - delimited)");
202 menu.Add(AK_FINDSTRINGBACK, THISBACK1(FindString, true))
203 .Help("Find any ordinary string constant (\"\" - delimited) backwards");
204 menu.MenuSeparator();
205 }
206 menu.Add(AK_FINDINFILES, THISBACK1(FindInFiles, false))
207 .Help("Find text or text pattern in subtree of given path");
208 menu.Add(AK_REPLACEINFILES, THISBACK1(FindInFiles, true))
209 .Help("Find text or text pattern in subtree of given path, with replace option(s)");
210 menu.Add(AK_FINDFILE, THISBACK(FindFileName))
211 .Help("Locate file by filename (use *, ? when you're not sure)");
212 }
213
Edit(Bar & menu)214 void Ide::Edit(Bar& menu)
215 {
216 bool b = !editor.IsReadOnly();
217 if(editfile.GetCount() && editashex.Find(editfile) < 0) {
218 menu.Add(AK_EDITASHEX, THISBACK(EditAsHex));
219 if(!designer)
220 menu.MenuSeparator();
221 }
222 if(designer) {
223 if(FileExists(designer->GetFileName())) {
224 menu.Add(AK_EDITASTEXT, THISBACK(EditAsText))
225 .Help("Edit as text file (do not use a designer)");
226 menu.MenuSeparator();
227 }
228 if(menu.IsMenuBar())
229 designer->EditMenu(menu);
230 }
231 else {
232 bool selection = editor.IsAnySelection();
233
234 if(editor.IsView()) {
235 menu.Add(AK_EDITASTEXT, THISBACK(EditAsText))
236 .Help("Edit file");
237 menu.MenuSeparator();
238 }
239 if(GetFileExt(editfile) == ".t") {
240 if(editastext.Find(editfile) >= 0)
241 menu.Add(AK_DESIGNER, THISBACK(EditUsingDesigner))
242 .Help("Edit converted strings");
243 else
244 menu.Add(AK_EDITASTEXT, THISBACK(EditAsText))
245 .Help("Edit raw strings");
246 menu.MenuSeparator();
247 }
248 else
249 if(editastext.Find(editfile) >= 0/* && IsDesignerFile(editfile)*/) {
250 menu.Add(AK_DESIGNER, THISBACK(EditUsingDesigner))
251 .Help(editor.GetLength() > 256*1024*1024 ? "View file" : "Edit using the designer (not as text)");
252 menu.MenuSeparator();
253 }
254 menu.Add(b, "Undo", CtrlImg::undo(), callback(&editor, &LineEdit::Undo))
255 .Key(K_CTRL_Z)
256 .Enable(editor.IsUndo())
257 .Help("Undo changes to text");
258 menu.Add(b, "Redo", CtrlImg::redo(), callback(&editor, &LineEdit::Redo))
259 .Key(K_SHIFT|K_CTRL_Z)
260 .Enable(editor.IsRedo())
261 .Help("Redo undone changes");
262
263 menu.Separator();
264
265 menu.Add(b, "Cut", CtrlImg::cut(), callback(&editor, &LineEdit::Cut))
266 .Key(K_CTRL_X)
267 .Enable(selection)
268 .Help("Cut selection and place it on the system clipboard");
269 menu.Add("Copy", CtrlImg::copy(), callback(&editor, &LineEdit::Copy))
270 .Key(K_CTRL_C)
271 .Enable(selection)
272 .Help("Copy current selection on the system clipboard");
273 menu.Add(b, "Paste", CtrlImg::paste(), THISBACK(EditPaste))
274 .Key(K_CTRL_V)
275 .Help("Insert text from clipboard at cursor location");
276
277 menu.Separator();
278
279 menu.Add("Select all", CtrlImg::select_all(), callback(&editor, &LineEdit::SelectAll))
280 .Key(K_CTRL_A);
281 }
282
283 menu.MenuSeparator();
284
285 menu.Add("Find and Replace", THISBACK(SearchMenu));
286
287 if(!designer && menu.IsMenuBar())
288 InsertAdvanced(menu);
289
290 if(editor.GetLineCount() && editor.GetUtf8Line(0) == "$uvs: PENDING CONFLICT") {
291 menu.MenuSeparator();
292 menu.Add("Resolve pending uvs conflict", THISBACK(ResolveUvsConflict))
293 .Help("Merge $uvs: pending conflicts generated by UVS series of versioning software");
294 }
295 }
296
HasMacros()297 bool Ide::HasMacros()
298 {
299 const Array<IdeMacro>& mlist = UscMacros();
300 if(!mlist.IsEmpty())
301 for(int i = 0; i < mlist.GetCount(); i++) {
302 const IdeMacro& m = mlist[i];
303 if(!IsNull(m.menu))
304 return true;
305 }
306 return false;
307 }
308
MacroMenu(Bar & menu)309 void Ide::MacroMenu(Bar& menu)
310 {
311 const Array<IdeMacro>& mlist = UscMacros();
312 if(!mlist.IsEmpty() && menu.IsMenuBar()) {
313 VectorMap< String, Vector<int> > submenu_map;
314 for(int i = 0; i < mlist.GetCount(); i++) {
315 const IdeMacro& m = mlist[i];
316 if(!IsNull(m.menu)) {
317 if(IsNull(m.submenu))
318 submenu_map.GetAdd(Null).Add(i);
319 else
320 submenu_map.GetAdd(m.menu).Add(i);
321 }
322 }
323 if(!submenu_map.IsEmpty()) {
324 Vector<int> order = GetSortOrder(submenu_map.GetKeys());
325 for(int o = 0; o < order.GetCount(); o++) {
326 String m = submenu_map.GetKey(order[o]);
327 Vector<int>& mx = submenu_map[order[o]];
328 ValueArray va;
329 for(int i = 0; i < mx.GetCount(); i++)
330 va.Add(mx[i]);
331 if(!IsNull(m))
332 menu.Add(m, THISBACK1(EditMacroMenu, va));
333 else
334 EditMacroMenu(menu, va);
335 }
336 }
337 }
338 }
339
EditMacroMenu(Bar & menu,ValueArray mx)340 void Ide::EditMacroMenu(Bar& menu, ValueArray mx)
341 {
342 const Array<IdeMacro>& mlist = UscMacros();
343 Vector<String> names;
344 Vector<int> index;
345 names.Reserve(mx.GetCount());
346 for(int i = 0; i < mx.GetCount(); i++) {
347 int ii = mx[i];
348 if(ii >= 0 && ii < mlist.GetCount()) {
349 const IdeMacro& m = mlist[ii];
350 names.Add(Nvl(m.submenu, m.menu));
351 index.Add(ii);
352 }
353 }
354 IndexSort(names, index);
355 for(int i = 0; i < index.GetCount(); i++)
356 menu.Add(names[i], THISBACK1(EditMacro, index[i]))
357 .Key(mlist[index[i]].hotkey);
358 }
359
EditMacro(int i)360 void Ide::EditMacro(int i)
361 {
362 const Array<IdeMacro>& mlist = UscMacros();
363 if(i >= 0 && i < mlist.GetCount()) {
364 const IdeMacro& m = mlist[i];
365 try {
366 Vector<EscValue> arg;
367 EscValue api = macro_api, code = m.code;
368 ::Execute(UscGlobal(), &api, code, arg, 1000000);
369 }
370 catch(Exc e) {
371 PutConsole(e);
372 }
373 }
374 }
375
Setup(Bar & menu)376 void Ide::Setup(Bar& menu)
377 {
378 menu.Add("Be verbose", THISBACK(ToggleVerboseBuild))
379 .Check(console.verbosebuild)
380 .Help("Log detailed description of build and debug");
381 menu.MenuSeparator();
382 menu.Add("Settings..", IdeImg::Settings(), THISBACK(SetupFormat))
383 .Help("Fonts, tabs, indentation, status bar");
384 menu.Add("Abbreviations..", THISBACK(Abbreviations))
385 .Help("Edit abbreviation keywords and code");
386 menu.Add("Keyboard shortcuts..", THISBACK(DoEditKeys))
387 .Help("Edit key bindings");
388 menu.Add("Macro Manager..", THISBACK(DoMacroManager))
389 .Help("Manage macros collection..");
390 menu.Add("Build methods..", THISBACK(SetupBuildMethods))
391 .Help("Setup build methods");
392 #ifdef PLATFORM_WIN32
393 menu.Add("Automatic build methods setup..", callback(InstantSetup))
394 .Help("Setups/fixes build methods and basic assemblies..");
395 #endif
396 menu.MenuSeparator();
397 menu.Add("Checkout and setup U++ SVN trunk sources..", [=] {
398 if(SetupSVNTrunk()) {
399 IdeAgain = true;
400 Break();
401 }
402 });
403
404 #ifndef PLATFORM_COCOA
405 const Workspace& wspc = IdeWorkspace();
406 if(wspc[0] == "ide")
407 for(int i = 0; i < wspc.GetCount(); i++)
408 if(wspc[i] == "ide/Core")
409 menu.Add("Upgrade TheIDE..", [=] { UpgradeTheIDE(); });
410 #ifdef PLATFORM_POSIX
411 menu.Add("Install theide.desktop", [=] { InstallDesktop(); });
412 #endif
413 #endif
414
415 if(menu.IsMenuBar())
416 SetupMobilePlatforms(menu);
417 }
418
SetupMobilePlatforms(Bar & menu)419 void Ide::SetupMobilePlatforms(Bar& menu)
420 {
421 AndroidSDK androidSDK(GetAndroidSdkPath());
422
423 if(androidSDK.Validate()) {
424 menu.Separator();
425 menu.Add("Android", THISBACK1(SetupAndroidMobilePlatform, androidSDK));
426 }
427
428 }
429
SetupAndroidMobilePlatform(Bar & menu,const AndroidSDK & androidSDK)430 void Ide::SetupAndroidMobilePlatform(Bar& menu, const AndroidSDK& androidSDK)
431 {
432 menu.Add("SDK Manager", THISBACK1(LaunchAndroidSDKManager, androidSDK));
433 menu.Add("AVD Manager", THISBACK1(LaunchAndroidAVDManager, androidSDK));
434 menu.Add("Device monitor", THISBACK1(LauchAndroidDeviceMonitor, androidSDK));
435 }
436
ProjectRepo(Bar & menu)437 void Ide::ProjectRepo(Bar& menu)
438 {
439 Vector<String> w = RepoDirs(true);
440 for(int i = 0; i < w.GetCount(); i++)
441 menu.Add("Synchronize " + w[i], IdeImg::svn_dir(), THISBACK1(SyncRepoDir, w[i]));
442 menu.Add("Synchronize everything..", IdeImg::svn(), THISBACK(SyncRepo));
443 }
444
Project(Bar & menu)445 void Ide::Project(Bar& menu)
446 {
447 if(menu.IsToolBar() && !debugger && !IsEditorMode())
448 {
449 mainconfiglist.Enable(idestate == EDITING);
450 buildmode.Enable(idestate == EDITING);
451 menu.Add(mainconfiglist, HorzLayoutZoom(180));
452 menu.Gap(4);
453 menu.Add(buildmode, HorzLayoutZoom(180));
454 menu.Separator();
455 }
456 if(!IsEditorMode()) {
457 WorkspaceWork::PackageMenu(menu);
458 menu.MenuSeparator();
459 menu.Add(AK_ORGANIZER, IdeImg::package_organizer(), THISBACK(EditWorkspace))
460 .Help("Package dependencies, compiler & linker options, output path override");
461 menu.Add(AK_CUSTOM, THISBACK(CustomSteps))
462 .Help("Building intermediate files using custom commands / applications");
463 if(menu.IsMenuBar())
464 menu.Add(AK_MAINCONFIG, IdeImg::main_package(), THISBACK(MainConfig))
465 .Help("Configuring compiler, operating system, output application parameters, custom flags");
466 menu.Separator();
467 menu.Add(AK_SYNCT, IdeImg::Language(), THISBACK1(SyncT, 0))
468 .Help("Synchronize all language translation files of current workspace");
469 menu.AddMenu(AK_TRIMPORT, IdeImg::Language(), THISBACK1(SyncT, 1))
470 .Help("Import runtime translation file");
471 menu.AddMenu(AK_TREXPORT, IdeImg::Language(), THISBACK1(SyncT, 2))
472 .Help("Export runtime translation file");
473 if(OldLang())
474 menu.Add("Convert s_ -> t_", THISBACK(ConvertST));
475 }
476 menu.MenuSeparator();
477 FilePropertiesMenu0(menu);
478 if(!IsEditorMode()) {
479 menu.MenuSeparator();
480 if(repo_dirs) {
481 if(menu.IsMenuBar())
482 menu.Add("Repo", THISBACK(ProjectRepo));
483 else
484 menu.Add("Synchronize all repositories..", IdeImg::svn(), THISBACK(SyncRepo));
485 }
486 }
487 }
488
FilePropertiesMenu0(Bar & menu)489 void Ide::FilePropertiesMenu0(Bar& menu)
490 {
491 menu.Add(IsActiveFile(), AK_FILEPROPERTIES, THISBACK(FileProperties))
492 .Help("File properties stored in package");
493 }
494
FilePropertiesMenu(Bar & menu)495 void Ide::FilePropertiesMenu(Bar& menu)
496 {
497 menu.Add(IsActiveFile() && !designer, AK_SAVEENCODING, THISBACK(ChangeCharset))
498 .Help("Convert actual file to different encoding");
499 menu.AddMenu(IsActiveFile() && !editfile_isfolder && !designer, AK_DIFF, IdeImg::Diff(), THISBACK(Diff))
500 .Help("Show differences between the current and arbitrary files");
501 menu.AddMenu(IsActiveFile() && !editfile_isfolder && !designer && GetTargetLogPath().GetCount(),
502 AK_DIFFLOG, IdeImg::DiffLog(), THISBACK(DiffLog))
503 .Help("Show differences between the current and arbitrary files");
504 if(editfile_repo) {
505 String txt = String("Show ") + (editfile_repo == SVN_DIR ? "svn" : "git") + " history of file";
506 menu.AddMenu(IsActiveFile() && !editfile_isfolder && !designer, AK_SVNDIFF, IdeImg::SvnDiff(), THISBACK(SvnHistory))
507 .Text(txt + "..").Help(txt);
508 if(editfile.GetCount()) {
509 String mine;
510 String theirs;
511 String original;
512 Vector<String> r;
513 Vector<int> rn;
514 if(editfile_repo == SVN_DIR) {
515 for(FindFile ff(editfile + ".*"); ff; ff.Next()) {
516 if(ff.IsFile()) {
517 String p = ff.GetPath();
518 if(p.Find(".merge-left.r") >= 0)
519 original = p;
520 if(p.Find(".merge-right.r") >= 0)
521 theirs = p;
522 if(p.Find(".working") >= 0 || p.Find(".mine") >= 0)
523 mine = p;
524 try {
525 CParser q(GetFileExt(~p));
526 q.PassChar('.');
527 q.PassChar('r');
528 int n = q.ReadInt();
529 if(q.IsEof()) {
530 r.Add(p);
531 rn.Add(n);
532 }
533 }
534 catch(CParser::Error) {}
535 }
536 }
537 if(IsNull(original) && IsNull(theirs) && r.GetCount() == 2) {
538 original = r[0];
539 theirs = r[1];
540 if(rn[1] > rn[0])
541 Swap(original, theirs);
542 }
543 }
544 else {
545 bool a = false, b = false, c = false;
546 int n = min(editor.GetLineCount(), 10000);
547 for(int i = 0; i < n; i++) { // check that we are in git conflict
548 const String& s = editor.GetUtf8Line(i);
549 int ch = *s;
550 a = a || ch == '<' && s.StartsWith("<<<<<<<");
551 b = b || ch == '=' && s.StartsWith("=======");
552 c = c || ch == '>' && s.StartsWith(">>>>>>>");
553 }
554 if(a && b && c) {
555 original = "1";
556 mine = "2";
557 theirs = "3";
558 }
559 }
560
561 if(mine.GetCount() || theirs.GetCount() || original.GetCount()) {
562 menu.Sub("SVN Conflict", [=] (Bar& bar) {
563 if(mine.GetCount() && theirs.GetCount())
564 bar.Add("Compare mine <-> theirs", [=] { DiffFiles("mine", mine, "theirs", theirs); });
565 if(mine.GetCount() && original.GetCount())
566 bar.Add("Compare mine <-> original", [=] { DiffFiles("mine", mine, "original", original); });
567 if(theirs.GetCount() && original.GetCount())
568 bar.Add("Compare theirs <-> original", [=] { DiffFiles("theirs", theirs, "original", original); });
569 if(mine.GetCount())
570 bar.Add("Compare current <-> mine", [=] { DiffFiles("current", editfile, "mine", mine); });
571 if(theirs.GetCount())
572 bar.Add("Compare current <-> theirs", [=] { DiffFiles("current", editfile, "theirs", theirs); });
573 if(original.GetCount())
574 bar.Add("Compare current <-> original", [=] { DiffFiles("current", editfile, "original", original); });
575 bar.Separator();
576 bar.Add("Use mine", [=] {
577 if(PromptYesNo("Do you want to overwrite current with [* mine]?")) {
578 SaveFile();
579 Upp::SaveFile(editfile, LoadConflictFile(mine));
580 }
581 });
582 bar.Add("Use theirs", [=] {
583 if(PromptYesNo("Do you want to overwrite current with [* theirs]?")) {
584 SaveFile();
585 Upp::SaveFile(editfile, LoadConflictFile(theirs));
586 }
587 });
588 });
589 }
590 }
591 if(editfile.GetCount() && editfile_repo == GIT_DIR) {
592 }
593 }
594 }
595
BuildFileMenu(Bar & menu)596 void Ide::BuildFileMenu(Bar& menu)
597 {
598 bool b = idestate == EDITING && !IdeIsDebugLock();
599 menu.Add(b, "Compile " + GetFileName(editfile), IdeImg::Source(), THISBACK(FileCompile))
600 .Key(AK_COMPILEFILE)
601 .Help("Compile current file");
602 menu.Add(b, "Preprocess " + GetFileName(editfile), IdeImg::Header(), THISBACK1(Preprocess, false))
603 .Key(AK_PREPROCESSFILE)
604 .Help("Preprocess current file into temporary file & open in editor");
605 if(findarg(current_builder, "GCC", "CLANG") >= 0)
606 menu.Add(b, "Show assembler code for " + GetFileName(editfile), THISBACK1(Preprocess, true))
607 .Key(AK_ASSEMBLERCODE)
608 .Help("Compile the file into assembler code");
609 if(console.verbosebuild)
610 menu.Add(b, "Internal Preprocess " + GetFileName(editfile), IdeImg::HeaderInternal(), THISBACK(PreprocessInternal));
611 }
612
BuildPackageMenu(Bar & menu)613 void Ide::BuildPackageMenu(Bar& menu)
614 {
615 int pi = GetPackageIndex();
616 bool b = !IdeIsDebugLock() && idestate == EDITING && pi >= 0 && pi < IdeWorkspace().GetCount();
617 String name;
618 if(b)
619 name = '\'' + IdeWorkspace()[pi] + '\'';
620 menu.Add(b, "Build package " + name, THISBACK(PackageBuild))
621 .Help("Build current package");
622 menu.Add(b, "Clean package " + name, THISBACK(PackageClean))
623 .Help("Remove all intermediate files of the current package");
624 menu.MenuSeparator();
625 }
626
BuildMenu(Bar & menu)627 void Ide::BuildMenu(Bar& menu)
628 {
629 bool b = !IdeIsDebugLock();
630 menu.Add(AK_OUTPUTMODE, THISBACK(SetupOutputMode))
631 .Help("Setup how to build the target");
632 if(idestate == BUILDING)
633 menu.Add(b, "Stop build", IdeImg::build_stop(), THISBACK(StopBuild))
634 .Key(AK_BUILD)
635 .Help("Stop building");
636 else
637 menu.Add(b, "Build", IdeImg::build_make(), THISBACK(DoBuild))
638 .Key(AK_BUILD)
639 .Help("Perform minimal application rebuild");
640 b = b && idestate == EDITING;
641 menu.Add(b, AK_CLEAN, THISBACK(Clean))
642 .Help("Remove all intermediate files");
643 menu.Add(b, AK_REBUILDALL, IdeImg::build_rebuild_all(), THISBACK(RebuildAll))
644 .Help("Remove all intermediate files & build");
645 menu.Add(b, AK_CLEANUPPOUT, THISBACK(CleanUppOut))
646 .Help("Remove all files and subdirectories in the output & intermediate directory (see Base setup)");
647
648 // menu.MenuSeparator();
649
650 // menu.Add(b, AK_CREATEMAKEFILE, THISBACK(CreateMakefile))
651 // .Help("Create makefile enabling IDE-independent project building");
652
653 menu.MenuSeparator();
654
655
656 if(menu.IsMenuBar() && !menu.IsScanKeys())
657 BuildPackageMenu(menu);
658
659 BuildFileMenu(menu);
660
661 menu.MenuSeparator();
662
663 menu.Add("Stop on errors", THISBACK(ToggleStopOnErrors))
664 .Check(stoponerrors)
665 .Help("Stop build after package when the package has errors");
666
667 menu.MenuSeparator();
668
669 bool ff = BottomIsFindInFiles();
670 String hh = ff ? "position" : "error line";
671 bool ffb = ff ? FFound().GetCount() : error.GetCount();
672 menu.Add(ffb, AK_FINDNEXTERROR, THISBACK(FindNextError))
673 .Help("Find next " + hh + "according to console pane");
674 menu.Add(ffb, AK_FINDPREVERROR, THISBACK(FindPrevError))
675 .Help("Find previous " + hh + "according to console pane");
676 #if defined(PLATFORM_WIN32) || defined(PLATFORM_POSIX)
677 menu.MenuSeparator();
678 menu.Add(!IsNull(target), AK_OPENOUTDIR, THISBACK(OpenOutputFolder));
679 #endif
680 }
681
DebugMenu(Bar & menu)682 void Ide::DebugMenu(Bar& menu)
683 {
684 bool b = idestate == EDITING && !IdeIsDebugLock();
685 if(debugger) {
686 debugger->DebugBar(menu);
687 menu.MenuSeparator();
688 }
689 else {
690 if(console.IsRunning())
691 menu.Add("Stop!", THISBACK(StopDebug))
692 .Help("Stop controlled process");
693 if(menu.IsMenuBar())
694 menu.Add(AK_RUNOPTIONS, THISBACK(RunArgs))
695 .Help("Current directory, command line, stdout redirection");
696 menu.Add(b, AK_EXECUTE, IdeImg::execute(), THISBACK(BuildAndExecute))
697 .Help("Build and execute the application");
698 menu.Add(b, AK_DEBUG, IdeImg::debug_run(), THISBACK1(BuildAndDebug, false))
699 .Help("Build application & run debugger");
700 if(menu.IsMenuBar()) {
701 menu.Add(b, AK_DEBUGTO, THISBACK1(BuildAndDebug, true))
702 .Help("Build application & run to cursor in debugger");
703 menu.Add(b, AK_DEBUGEXT, THISBACK(BuildAndExtDebug))
704 .Help("Build application & run external debugger (see Base setup, default \"msdev.exe\")");
705 menu.Add(b, AK_DEBUGFILEEXT, THISBACK(BuildAndExtDebugFile))
706 .Help("Build application & run external debugger, trying to start with current file");
707 #ifdef PLATFORM_POSIX
708 if(IsValgrind())
709 menu.Add(b, AK_VALGRIND, THISBACK(Valgrind))
710 .Help("Build application & run in valgring");
711 #endif
712
713 menu.Separator();
714 }
715 }
716 if(menu.IsMenuBar()) {
717 menu.Add(!editfile.IsEmpty() /*&& !debuglock*/, AK_BREAKPOINT, THISBACK(DebugToggleBreak))
718 .Help("Set / clear breakpoint on current line");
719 menu.Add(!editfile.IsEmpty(), AK_CONDBREAKPOINT, THISBACK(ConditionalBreak))
720 .Help("Edit conditional breakpoint");
721 menu.Add(!editfile.IsEmpty() /*&& !debuglock*/, AK_CLEARBREAKPOINTS, THISBACK(DebugClearBreakpoints))
722 .Help("Clear all breakpoints");
723 menu.Separator();
724
725 String targetLogPath = GetTargetLogPath();
726 menu.Add(target.GetCount() && FileExists(targetLogPath), AK_OPENLOG, THISBACK1(OpenLog, targetLogPath));
727 }
728 }
729
BrowseMenu(Bar & menu)730 void Ide::BrowseMenu(Bar& menu)
731 {
732 if(!IsEditorMode()) {
733 if(menu.IsMenuBar()) {
734 menu.AddMenu(AK_NAVIGATOR, IdeImg::Navigator(), THISBACK(ToggleNavigator))
735 .Check(editor.IsNavigator())
736 .Enable(!designer);
737 menu.Add(AK_GOTO, THISBACK(SearchCode))
738 .Enable(!designer)
739 .Help("Go to given line");
740 menu.Add(AK_GOTOGLOBAL, THISBACK(NavigatorDlg));
741 menu.Add(!designer, AK_JUMPS, THISBACK(ContextGoto));
742 menu.Add(!designer, AK_SWAPS, THISBACK(SwapS));
743 menu.Add(!designer, AK_ASSIST, callback(&editor, &AssistEditor::Assist));
744 menu.Add(!designer, AK_DCOPY, callback(&editor, &AssistEditor::DCopy));
745 menu.Add(!designer, AK_VIRTUALS, callback(&editor, &AssistEditor::Virtuals));
746 menu.Add(!designer, AK_THISBACKS, callback(&editor, &AssistEditor::Thisbacks));
747 menu.Add(!designer, AK_COMPLETE, callback(&editor, &AssistEditor::Complete));
748 menu.Add(!designer, AK_ABBR, callback(&editor, &AssistEditor::Abbr));
749 menu.Add(!designer, AK_GO_TO_LINE, THISBACK(GoToLine));
750 AssistEdit(menu);
751 menu.MenuSeparator();
752 }
753
754 menu.Add("Go back", IdeImg::AssistGoBack(), THISBACK1(History, -1))
755 .Key(K_ALT_LEFT)
756 .Enable(GetHistory(-1) >= 0);
757 menu.Add("Go forward", IdeImg::AssistGoForward(), THISBACK1(History, 1))
758 .Key(K_ALT_RIGHT)
759 .Enable(GetHistory(1) >= 0);
760
761 if(menu.IsMenuBar()) {
762 menu.MenuSeparator();
763 menu.Add("Check source files for changes", THISBACK(CheckCodeBase));
764 menu.Add("Rescan all source files", THISBACK(RescanCode));
765 if(!auto_rescan)
766 menu.Add(AK_RESCANCURRENTFILE, THISBACK(EditFileAssistSync));
767 menu.MenuSeparator();
768 }
769 }
770 else {
771 menu.Add(!designer, AK_GO_TO_LINE, THISBACK(GoToLine));
772 menu.MenuSeparator();
773 }
774
775 if(menu.IsMenuBar()) {
776 menu.AddMenu(AK_CALC, IdeImg::calc(), THISBACK1(ToggleBottom, BCALC))
777 .Check(IsBottomShown() && btabs.GetCursor() == BCALC);
778 menu.AddMenu(AK_QTF, IdeCommonImg::Qtf(), THISBACK(Qtf));
779 menu.AddMenu(!designer, AK_XML, IdeCommonImg::xml(), THISBACK(Xml));
780 menu.AddMenu(!designer, AK_JSON, IdeCommonImg::json(), THISBACK(Json));
781 menu.AddMenu(!designer, AK_ASERRORS, IdeImg::errors(), THISBACK(AsErrors));
782 menu.AddMenu(AK_DIRDIFF, DiffImg::DirDiff(), THISBACK(DoDirDiff));
783 menu.AddMenu(AK_PATCH, DiffImg::PatchDiff(), THISBACK(DoPatchDiff));
784 }
785 }
786
HelpMenu(Bar & menu)787 void Ide::HelpMenu(Bar& menu)
788 {
789 if(!IsEditorMode()) {
790 menu.Add(AK_BROWSETOPICS, IdeImg::help(), THISBACK(ShowTopics));
791 menu.Add(AK_SEARCHTOPICS, THISBACK(SearchTopics));
792 }
793 menu.Add(AK_BROWSETOPICS_WIN, IdeImg::help_win(), THISBACK(ShowTopicsWin));
794 menu.MenuSeparator();
795 menu.AddMenu("Get help / report bugs..", IdeImg::Go_forward(), callback1(LaunchWebBrowser, "http://www.ultimatepp.org/forums"));
796 menu.AddMenu("Online documentation..", IdeImg::Go_forward(), callback1(LaunchWebBrowser, "http://www.ultimatepp.org/www$uppweb$documentation$en-us.html"));
797 menu.AddMenu("Common information..", IdeImg::Go_forward(), callback1(LaunchWebBrowser, "http://www.ultimatepp.org/www$uppweb$community$en-us.html"));
798 menu.Separator();
799 OnlineSearchMenu(menu);
800 if(menu.IsMenuBar()) {
801 menu.Separator();
802 menu.Add(FileExists(GetIdeLogPath()), "View application log file", THISBACK(ViewIdeLogFile));
803 menu.Separator();
804 menu.Add("About..", IdeImg::info(), THISBACK(About));
805 }
806 }
807
MainMenu(Bar & menu)808 void Ide::MainMenu(Bar& menu)
809 {
810 menu.Add("File", THISBACK(File))
811 .Help("Package & file functions, exports, bookmarks");
812 menu.Add("Edit", THISBACK(Edit))
813 .Help("Clipboard, find & replace, spaces / tabs conversion, scope highlighting");
814 if(HasMacros())
815 menu.Add("Macro", THISBACK(MacroMenu))
816 .Help("Editor & IDE macros");
817 menu.Add("Project", THISBACK(Project))
818 .Help("Package organizer, custom steps, configuration manager");
819 if(!IsEditorMode()) {
820 menu.Add("Build", THISBACK(BuildMenu))
821 .Help("Building & debugging, minor build options, showing errors");
822 menu.Add("Debug", THISBACK(DebugMenu))
823 .Help("Debugger commands (currently supports gdb-connection only)");
824 }
825 menu.Add("Assist", THISBACK(BrowseMenu))
826 .Help("Informations, code browsing and assistance");
827 menu.Add("Setup", THISBACK(Setup))
828 .Help("Paths, editor settings, connection to remote host");
829 menu.Add("Help", THISBACK(HelpMenu))
830 .Help("Help, credits and license");
831 }
832
MainTool(Bar & bar)833 void Ide::MainTool(Bar& bar)
834 {
835 if(!IsEditorMode()) {
836 BrowseMenu(bar);
837 bar.Separator();
838 }
839 bar.Add("Edit as text", IdeImg::EditText(), THISBACK(EditAsText))
840 .Check(!designer)
841 .Enable(!editfile_isfolder)
842 .Key(!designer ? 0 : K_CTRL_T);
843 bool b = designer && !designer.Is<FileHexView>();
844 bool d = IsDesignerFile(editfile);
845 bar.Add("Edit using designer", IdeImg::EditDesigner(), THISBACK(EditUsingDesigner))
846 .Check(b || editfile_isfolder)
847 .Enable(d || editfile_isfolder)
848 .Key(b || !d ? 0 : K_CTRL_T);
849 bar.Add("View as hex", IdeImg::EditHex(), THISBACK(EditAsHex))
850 .Check(designer.Is<FileHexView>())
851 .Enable(!editfile_isfolder)
852 .Key(K_CTRL_B);
853 if(!designer)
854 bar.Separator();
855 Edit(bar);
856 if(debugger) {
857 DebugMenu(bar);
858 bar.Separator();
859 }
860 Project(bar);
861 if(!IsEditorMode()) {
862 BuildMenu(bar);
863 if(!debugger) {
864 bar.Separator();
865 DebugMenu(bar);
866 }
867 bar.Separator();
868 }
869 HelpMenu(bar);
870 #ifdef PLATFORM_COCOA
871 bar.GapRight();
872 bar.Add(display, HorzLayoutZoom(170));
873 #endif
874 }
875
ConsoleMenu(Bar & menu)876 void Ide::ConsoleMenu(Bar& menu)
877 {
878 bool selection = console.IsAnySelection();
879 menu.Add("Copy", CtrlImg::copy(), THISBACK(ConsoleCopy))
880 .Key(K_CTRL_C)
881 .Enable(selection)
882 .Help("Copy selection on system clipboard");
883 menu.Add("Paste", CtrlImg::paste(), THISBACK(ConsolePaste))
884 .Key(K_CTRL_V)
885 .Help("Append selection to system console");
886 menu.Separator();
887 menu.Add(AK_FIND, [=] {
888 console.FindReplace(false, true, false);
889 });
890 menu.Separator();
891 menu.Add("Clear", THISBACK(ConsoleClear))
892 .Help("Empty system console");
893 }
894
SetBar()895 void Ide::SetBar()
896 {
897 SetMenuBar();
898 SetToolBar();
899 }
900
SetMenuBar()901 void Ide::SetMenuBar()
902 {
903 #ifdef PLATFORM_COCOA
904 SetMainMenu(THISBACK(MainMenu));
905 menubar.Hide();
906 #else
907 menubar.Set(THISBACK(MainMenu));
908 #endif
909 }
910
SetToolBar()911 void Ide::SetToolBar()
912 {
913 toolbar.Set(THISBACK(MainTool));
914 }
915