diff options
Diffstat (limited to 'tests/examplefiles/example.nim')
-rw-r--r-- | tests/examplefiles/example.nim | 1010 |
1 files changed, 1010 insertions, 0 deletions
diff --git a/tests/examplefiles/example.nim b/tests/examplefiles/example.nim new file mode 100644 index 00000000..319da016 --- /dev/null +++ b/tests/examplefiles/example.nim @@ -0,0 +1,1010 @@ +import glib2, gtk2, gdk2, gtksourceview, dialogs, os, pango, osproc, strutils +import pegs, streams +import settings, types, cfg, search + +{.push callConv:cdecl.} + +const + NimrodProjectExt = ".nimprj" + +var win: types.MainWin +win.Tabs = @[] + +search.win = addr(win) + +var lastSession: seq[string] = @[] + +var confParseFail = False # This gets set to true + # When there is an error parsing the config + +# Load the settings +try: + win.settings = cfg.load(lastSession) +except ECFGParse: + # TODO: Make the dialog show the exception + confParseFail = True + win.settings = cfg.defaultSettings() +except EIO: + win.settings = cfg.defaultSettings() + +proc getProjectTab(): int = + for i in 0..high(win.tabs): + if win.tabs[i].filename.endswith(NimrodProjectExt): return i + +proc saveTab(tabNr: int, startpath: string) = + if tabNr < 0: return + if win.Tabs[tabNr].saved: return + var path = "" + if win.Tabs[tabNr].filename == "": + path = ChooseFileToSave(win.w, startpath) + # dialogs.nim STOCK_OPEN instead of STOCK_SAVE + else: + path = win.Tabs[tabNr].filename + + if path != "": + var buffer = PTextBuffer(win.Tabs[tabNr].buffer) + # Get the text from the TextView + var startIter: TTextIter + buffer.getStartIter(addr(startIter)) + + var endIter: TTextIter + buffer.getEndIter(addr(endIter)) + + var text = buffer.getText(addr(startIter), addr(endIter), False) + # Save it to a file + var f: TFile + if open(f, path, fmWrite): + f.write(text) + f.close() + + win.tempStuff.lastSaveDir = splitFile(path).dir + + # Change the tab name and .Tabs.filename etc. + win.Tabs[tabNr].filename = path + win.Tabs[tabNr].saved = True + var name = extractFilename(path) + + var cTab = win.Tabs[tabNr] + cTab.label.setText(name) + else: + error(win.w, "Unable to write to file") + +proc saveAllTabs() = + for i in 0..high(win.tabs): + saveTab(i, os.splitFile(win.tabs[i].filename).dir) + +# GTK Events +# -- w(PWindow) +proc destroy(widget: PWidget, data: pgpointer) {.cdecl.} = + # gather some settings + win.settings.VPanedPos = PPaned(win.sourceViewTabs.getParent()).getPosition() + win.settings.winWidth = win.w.allocation.width + win.settings.winHeight = win.w.allocation.height + + # save the settings + win.save() + # then quit + main_quit() + +proc delete_event(widget: PWidget, event: PEvent, user_data: pgpointer): bool = + var quit = True + for i in low(win.Tabs)..len(win.Tabs)-1: + if not win.Tabs[i].saved: + var askSave = dialogNewWithButtons("", win.w, 0, + STOCK_SAVE, RESPONSE_ACCEPT, STOCK_CANCEL, + RESPONSE_CANCEL, + "Close without saving", RESPONSE_REJECT, nil) + askSave.setTransientFor(win.w) + # TODO: Make this dialog look better + var label = labelNew(win.Tabs[i].filename & + " is unsaved, would you like to save it ?") + PBox(askSave.vbox).pack_start(label, False, False, 0) + label.show() + + var resp = askSave.run() + gtk2.destroy(PWidget(askSave)) + case resp + of RESPONSE_ACCEPT: + saveTab(i, os.splitFile(win.tabs[i].filename).dir) + quit = True + of RESPONSE_CANCEL: + quit = False + break + of RESPONSE_REJECT: + quit = True + else: + quit = False + break + + # If False is returned the window will close + return not quit + +proc windowState_Changed(widget: PWidget, event: PEventWindowState, + user_data: pgpointer) = + win.settings.winMaximized = (event.newWindowState and + WINDOW_STATE_MAXIMIZED) != 0 + +# -- SourceView(PSourceView) & SourceBuffer +proc updateStatusBar(buffer: PTextBuffer){.cdecl.} = + # Incase this event gets fired before + # bottomBar is initialized + if win.bottomBar != nil and not win.tempStuff.stopSBUpdates: + var iter: TTextIter + + win.bottomBar.pop(0) + buffer.getIterAtMark(addr(iter), buffer.getInsert()) + var row = getLine(addr(iter)) + 1 + var col = getLineOffset(addr(iter)) + discard win.bottomBar.push(0, "Line: " & $row & " Column: " & $col) + +proc cursorMoved(buffer: PTextBuffer, location: PTextIter, + mark: PTextMark, user_data: pgpointer){.cdecl.} = + updateStatusBar(buffer) + +proc onCloseTab(btn: PButton, user_data: PWidget) = + if win.sourceViewTabs.getNPages() > 1: + var tab = win.sourceViewTabs.pageNum(user_data) + win.sourceViewTabs.removePage(tab) + + win.Tabs.delete(tab) + +proc onSwitchTab(notebook: PNotebook, page: PNotebookPage, pageNum: guint, + user_data: pgpointer) = + if win.Tabs.len()-1 >= pageNum: + win.w.setTitle("Aporia IDE - " & win.Tabs[pageNum].filename) + +proc createTabLabel(name: string, t_child: PWidget): tuple[box: PWidget, + label: PLabel] = + var box = hboxNew(False, 0) + var label = labelNew(name) + var closebtn = buttonNew() + closeBtn.setLabel(nil) + var iconSize = iconSizeFromName("tabIconSize") + if iconSize == 0: + iconSize = iconSizeRegister("tabIconSize", 10, 10) + var image = imageNewFromStock(STOCK_CLOSE, iconSize) + discard gSignalConnect(closebtn, "clicked", G_Callback(onCloseTab), t_child) + closebtn.setImage(image) + gtk2.setRelief(closebtn, RELIEF_NONE) + box.packStart(label, True, True, 0) + box.packEnd(closebtn, False, False, 0) + box.showAll() + return (box, label) + +proc changed(buffer: PTextBuffer, user_data: pgpointer) = + # Update the 'Line & Column' + #updateStatusBar(buffer) + + # Change the tabs state to 'unsaved' + # and add '*' to the Tab Name + var current = win.SourceViewTabs.getCurrentPage() + var name = "" + if win.Tabs[current].filename == "": + win.Tabs[current].saved = False + name = "Untitled *" + else: + win.Tabs[current].saved = False + name = extractFilename(win.Tabs[current].filename) & " *" + + var cTab = win.Tabs[current] + cTab.label.setText(name) + +# Other(Helper) functions + +proc initSourceView(SourceView: var PWidget, scrollWindow: var PScrolledWindow, + buffer: var PSourceBuffer) = + # This gets called by addTab + # Each tabs creates a new SourceView + # SourceScrolledWindow(ScrolledWindow) + scrollWindow = scrolledWindowNew(nil, nil) + scrollWindow.setPolicy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) + scrollWindow.show() + + # SourceView(gtkSourceView) + SourceView = sourceViewNew(buffer) + PSourceView(SourceView).setInsertSpacesInsteadOfTabs(True) + PSourceView(SourceView).setIndentWidth(win.settings.indentWidth) + PSourceView(SourceView).setShowLineNumbers(win.settings.showLineNumbers) + PSourceView(SourceView).setHighlightCurrentLine( + win.settings.highlightCurrentLine) + PSourceView(SourceView).setShowRightMargin(win.settings.rightMargin) + PSourceView(SourceView).setAutoIndent(win.settings.autoIndent) + + var font = font_description_from_string(win.settings.font) + SourceView.modifyFont(font) + + scrollWindow.add(SourceView) + SourceView.show() + + buffer.setHighlightMatchingBrackets( + win.settings.highlightMatchingBrackets) + + # UGLY workaround for yet another compiler bug: + discard gsignalConnect(buffer, "mark-set", + GCallback(aporia.cursorMoved), nil) + discard gsignalConnect(buffer, "changed", GCallback(aporia.changed), nil) + + # -- Set the syntax highlighter scheme + buffer.setScheme(win.scheme) + +proc addTab(name, filename: string) = + ## Adds a tab, if filename is not "" reads the file. And sets + ## the tabs SourceViews text to that files contents. + assert(win.nimLang != nil) + var buffer: PSourceBuffer = sourceBufferNew(win.nimLang) + + if filename != nil and filename != "": + var lang = win.langMan.guessLanguage(filename, nil) + if lang != nil: + buffer.setLanguage(lang) + else: + buffer.setHighlightSyntax(False) + + var nam = name + if nam == "": nam = "Untitled" + if filename == "": nam.add(" *") + elif filename != "" and name == "": + # Disable the undo/redo manager. + buffer.begin_not_undoable_action() + + # Load the file. + var file: string = readFile(filename) + if file != nil: + buffer.set_text(file, len(file)) + + # Enable the undo/redo manager. + buffer.end_not_undoable_action() + + # Get the name.ext of the filename, for the tabs title + nam = extractFilename(filename) + + # Init the sourceview + var sourceView: PWidget + var scrollWindow: PScrolledWindow + initSourceView(sourceView, scrollWindow, buffer) + + var (TabLabel, labelText) = createTabLabel(nam, scrollWindow) + # Add a tab + discard win.SourceViewTabs.appendPage(scrollWindow, TabLabel) + + var nTab: Tab + nTab.buffer = buffer + nTab.sourceView = sourceView + nTab.label = labelText + nTab.saved = (filename != "") + nTab.filename = filename + win.Tabs.add(nTab) + + PTextView(SourceView).setBuffer(nTab.buffer) + +# GTK Events Contd. +# -- TopMenu & TopBar + +proc newFile(menuItem: PMenuItem, user_data: pgpointer) = + addTab("", "") + win.sourceViewTabs.setCurrentPage(win.Tabs.len()-1) + +proc openFile(menuItem: PMenuItem, user_data: pgpointer) = + var startpath = "" + var currPage = win.SourceViewTabs.getCurrentPage() + if currPage <% win.tabs.len: + startpath = os.splitFile(win.tabs[currPage].filename).dir + + if startpath.len == 0: + # Use lastSavePath as the startpath + startpath = win.tempStuff.lastSaveDir + if startpath.len == 0: + startpath = os.getHomeDir() + + var files = ChooseFilesToOpen(win.w, startpath) + if files.len() > 0: + for f in items(files): + try: + addTab("", f) + except EIO: + error(win.w, "Unable to read from file") + # Switch to the newly created tab + win.sourceViewTabs.setCurrentPage(win.Tabs.len()-1) + +proc saveFile_Activate(menuItem: PMenuItem, user_data: pgpointer) = + var current = win.SourceViewTabs.getCurrentPage() + saveTab(current, os.splitFile(win.tabs[current].filename).dir) + +proc saveFileAs_Activate(menuItem: PMenuItem, user_data: pgpointer) = + var current = win.SourceViewTabs.getCurrentPage() + var (filename, saved) = (win.Tabs[current].filename, win.Tabs[current].saved) + + win.Tabs[current].saved = False + win.Tabs[current].filename = "" + saveTab(current, os.splitFile(filename).dir) + # If the user cancels the save file dialog. Restore the previous filename + # and saved state + if win.Tabs[current].filename == "": + win.Tabs[current].filename = filename + win.Tabs[current].saved = saved + +proc undo(menuItem: PMenuItem, user_data: pgpointer) = + var current = win.SourceViewTabs.getCurrentPage() + if win.Tabs[current].buffer.canUndo(): + win.Tabs[current].buffer.undo() + +proc redo(menuItem: PMenuItem, user_data: pgpointer) = + var current = win.SourceViewTabs.getCurrentPage() + if win.Tabs[current].buffer.canRedo(): + win.Tabs[current].buffer.redo() + +proc find_Activate(menuItem: PMenuItem, user_data: pgpointer) = + # Get the selected text, and set the findEntry to it. + var currentTab = win.SourceViewTabs.getCurrentPage() + var insertIter: TTextIter + win.Tabs[currentTab].buffer.getIterAtMark(addr(insertIter), + win.Tabs[currentTab].buffer.getInsert()) + var insertOffset = addr(insertIter).getOffset() + + var selectIter: TTextIter + win.Tabs[currentTab].buffer.getIterAtMark(addr(selectIter), + win.Tabs[currentTab].buffer.getSelectionBound()) + var selectOffset = addr(selectIter).getOffset() + + if insertOffset != selectOffset: + var text = win.Tabs[currentTab].buffer.getText(addr(insertIter), + addr(selectIter), false) + win.findEntry.setText(text) + + win.findBar.show() + win.findEntry.grabFocus() + win.replaceEntry.hide() + win.replaceLabel.hide() + win.replaceBtn.hide() + win.replaceAllBtn.hide() + +proc replace_Activate(menuitem: PMenuItem, user_data: pgpointer) = + win.findBar.show() + win.findEntry.grabFocus() + win.replaceEntry.show() + win.replaceLabel.show() + win.replaceBtn.show() + win.replaceAllBtn.show() + +proc settings_Activate(menuitem: PMenuItem, user_data: pgpointer) = + settings.showSettings(win) + +proc viewBottomPanel_Toggled(menuitem: PCheckMenuItem, user_data: pgpointer) = + win.settings.bottomPanelVisible = menuitem.itemGetActive() + if win.settings.bottomPanelVisible: + win.bottomPanelTabs.show() + else: + win.bottomPanelTabs.hide() + +var + pegLineError = peg"{[^(]*} '(' {\d+} ', ' \d+ ') Error:' \s* {.*}" + pegLineWarning = peg"{[^(]*} '(' {\d+} ', ' \d+ ') ' ('Warning:'/'Hint:') \s* {.*}" + pegOtherError = peg"'Error:' \s* {.*}" + pegSuccess = peg"'Hint: operation successful'.*" + +proc addText(textView: PTextView, text: string, colorTag: PTextTag = nil) = + if text != nil: + var iter: TTextIter + textView.getBuffer().getEndIter(addr(iter)) + + if colorTag == nil: + textView.getBuffer().insert(addr(iter), text, len(text)) + else: + textView.getBuffer().insertWithTags(addr(iter), text, len(text), colorTag, + nil) + +proc createColor(textView: PTextView, name, color: string): PTextTag = + var tagTable = textView.getBuffer().getTagTable() + result = tagTable.tableLookup(name) + if result == nil: + result = textView.getBuffer().createTag(name, "foreground", color, nil) + +when not defined(os.findExe): + proc findExe(exe: string): string = + ## returns "" if the exe cannot be found + result = addFileExt(exe, os.exeExt) + if ExistsFile(result): return + var path = os.getEnv("PATH") + for candidate in split(path, pathSep): + var x = candidate / result + if ExistsFile(x): return x + result = "" + +proc GetCmd(cmd, filename: string): string = + var f = quoteIfContainsWhite(filename) + if cmd =~ peg"\s* '$' y'findExe' '(' {[^)]+} ')' {.*}": + var exe = quoteIfContainsWhite(findExe(matches[0])) + if exe.len == 0: exe = matches[0] + result = exe & " " & matches[1] % f + else: + result = cmd % f + +proc showBottomPanel() = + if not win.settings.bottomPanelVisible: + win.bottomPanelTabs.show() + win.settings.bottomPanelVisible = true + PCheckMenuItem(win.viewBottomPanelMenuItem).itemSetActive(true) + # Scroll to the end of the TextView + # This is stupid, it works sometimes... it's random + var endIter: TTextIter + win.outputTextView.getBuffer().getEndIter(addr(endIter)) + discard win.outputTextView.scrollToIter( + addr(endIter), 0.25, False, 0.0, 0.0) + +proc compileRun(currentTab: int, shouldRun: bool) = + if win.Tabs[currentTab].filename.len == 0: return + # Clear the outputTextView + win.outputTextView.getBuffer().setText("", 0) + + var outp = osProc.execProcess(GetCmd(win.settings.nimrodCmd, + win.Tabs[currentTab].filename)) + # Colors + var normalTag = createColor(win.outputTextView, "normalTag", "#3d3d3d") + var errorTag = createColor(win.outputTextView, "errorTag", "red") + var warningTag = createColor(win.outputTextView, "warningTag", "darkorange") + var successTag = createColor(win.outputTextView, "successTag", "darkgreen") + for x in outp.splitLines(): + if x =~ pegLineError / pegOtherError: + win.outputTextView.addText("\n" & x, errorTag) + elif x=~ pegSuccess: + win.outputTextView.addText("\n" & x, successTag) + + # Launch the process + if shouldRun: + var filename = changeFileExt(win.Tabs[currentTab].filename, os.ExeExt) + var output = "\n" & osProc.execProcess(filename) + win.outputTextView.addText(output) + elif x =~ pegLineWarning: + win.outputTextView.addText("\n" & x, warningTag) + else: + win.outputTextView.addText("\n" & x, normalTag) + showBottomPanel() + +proc CompileCurrent_Activate(menuitem: PMenuItem, user_data: pgpointer) = + saveFile_Activate(nil, nil) + compileRun(win.SourceViewTabs.getCurrentPage(), false) + +proc CompileRunCurrent_Activate(menuitem: PMenuItem, user_data: pgpointer) = + saveFile_Activate(nil, nil) + compileRun(win.SourceViewTabs.getCurrentPage(), true) + +proc CompileProject_Activate(menuitem: PMenuItem, user_data: pgpointer) = + saveAllTabs() + compileRun(getProjectTab(), false) + +proc CompileRunProject_Activate(menuitem: PMenuItem, user_data: pgpointer) = + saveAllTabs() + compileRun(getProjectTab(), true) + +proc RunCustomCommand(cmd: string) = + saveFile_Activate(nil, nil) + var currentTab = win.SourceViewTabs.getCurrentPage() + if win.Tabs[currentTab].filename.len == 0 or cmd.len == 0: return + # Clear the outputTextView + win.outputTextView.getBuffer().setText("", 0) + var outp = osProc.execProcess(GetCmd(cmd, win.Tabs[currentTab].filename)) + var normalTag = createColor(win.outputTextView, "normalTag", "#3d3d3d") + for x in outp.splitLines(): + win.outputTextView.addText("\n" & x, normalTag) + showBottomPanel() + +proc RunCustomCommand1(menuitem: PMenuItem, user_data: pgpointer) = + RunCustomCommand(win.settings.customCmd1) + +proc RunCustomCommand2(menuitem: PMenuItem, user_data: pgpointer) = + RunCustomCommand(win.settings.customCmd2) + +proc RunCustomCommand3(menuitem: PMenuItem, user_data: pgpointer) = + RunCustomCommand(win.settings.customCmd3) + +# -- FindBar + +proc nextBtn_Clicked(button: PButton, user_data: pgpointer) = findText(True) +proc prevBtn_Clicked(button: PButton, user_data: pgpointer) = findText(False) + +proc replaceBtn_Clicked(button: PButton, user_data: pgpointer) = + var currentTab = win.SourceViewTabs.getCurrentPage() + var start, theEnd: TTextIter + if not win.Tabs[currentTab].buffer.getSelectionBounds( + addr(start), addr(theEnd)): + # If no text is selected, try finding a match. + findText(True) + if not win.Tabs[currentTab].buffer.getSelectionBounds( + addr(start), addr(theEnd)): + # No match + return + + # Remove the text + win.Tabs[currentTab].buffer.delete(addr(start), addr(theEnd)) + # Insert the replacement + var text = getText(win.replaceEntry) + win.Tabs[currentTab].buffer.insert(addr(start), text, len(text)) + +proc replaceAllBtn_Clicked(button: PButton, user_data: pgpointer) = + var find = getText(win.findEntry) + var replace = getText(win.replaceEntry) + discard replaceAll(find, replace) + +proc closeBtn_Clicked(button: PButton, user_data: pgpointer) = + win.findBar.hide() + +proc caseSens_Changed(radiomenuitem: PRadioMenuitem, user_data: pgpointer) = + win.settings.search = "casesens" +proc caseInSens_Changed(radiomenuitem: PRadioMenuitem, user_data: pgpointer) = + win.settings.search = "caseinsens" +proc style_Changed(radiomenuitem: PRadioMenuitem, user_data: pgpointer) = + win.settings.search = "style" +proc regex_Changed(radiomenuitem: PRadioMenuitem, user_data: pgpointer) = + win.settings.search = "regex" +proc peg_Changed(radiomenuitem: PRadioMenuitem, user_data: pgpointer) = + win.settings.search = "peg" + +proc extraBtn_Clicked(button: PButton, user_data: pgpointer) = + var extraMenu = menuNew() + var group: PGSList + + var caseSensMenuItem = radio_menu_item_new(group, "Case sensitive") + extraMenu.append(caseSensMenuItem) + discard signal_connect(caseSensMenuItem, "toggled", + SIGNAL_FUNC(caseSens_Changed), nil) + caseSensMenuItem.show() + group = caseSensMenuItem.ItemGetGroup() + + var caseInSensMenuItem = radio_menu_item_new(group, "Case insensitive") + extraMenu.append(caseInSensMenuItem) + discard signal_connect(caseInSensMenuItem, "toggled", + SIGNAL_FUNC(caseInSens_Changed), nil) + caseInSensMenuItem.show() + group = caseInSensMenuItem.ItemGetGroup() + + var styleMenuItem = radio_menu_item_new(group, "Style insensitive") + extraMenu.append(styleMenuItem) + discard signal_connect(styleMenuItem, "toggled", + SIGNAL_FUNC(style_Changed), nil) + styleMenuItem.show() + group = styleMenuItem.ItemGetGroup() + + var regexMenuItem = radio_menu_item_new(group, "Regex") + extraMenu.append(regexMenuItem) + discard signal_connect(regexMenuItem, "toggled", + SIGNAL_FUNC(regex_Changed), nil) + regexMenuItem.show() + group = regexMenuItem.ItemGetGroup() + + var pegMenuItem = radio_menu_item_new(group, "Pegs") + extraMenu.append(pegMenuItem) + discard signal_connect(pegMenuItem, "toggled", + SIGNAL_FUNC(peg_Changed), nil) + pegMenuItem.show() + + # Make the correct radio button active + case win.settings.search + of "casesens": + PCheckMenuItem(caseSensMenuItem).ItemSetActive(True) + of "caseinsens": + PCheckMenuItem(caseInSensMenuItem).ItemSetActive(True) + of "style": + PCheckMenuItem(styleMenuItem).ItemSetActive(True) + of "regex": + PCheckMenuItem(regexMenuItem).ItemSetActive(True) + of "peg": + PCheckMenuItem(pegMenuItem).ItemSetActive(True) + + extraMenu.popup(nil, nil, nil, nil, 0, get_current_event_time()) + +# GUI Initialization + +proc createAccelMenuItem(toolsMenu: PMenu, accGroup: PAccelGroup, + label: string, acc: gint, + action: proc (i: PMenuItem, p: pgpointer)) = + var result = menu_item_new(label) + result.addAccelerator("activate", accGroup, acc, 0, ACCEL_VISIBLE) + ToolsMenu.append(result) + show(result) + discard signal_connect(result, "activate", SIGNAL_FUNC(action), nil) + +proc createSeparator(menu: PMenu) = + var sep = separator_menu_item_new() + menu.append(sep) + sep.show() + +proc initTopMenu(MainBox: PBox) = + # Create a accelerator group, used for shortcuts + # like CTRL + S in SaveMenuItem + var accGroup = accel_group_new() + add_accel_group(win.w, accGroup) + + # TopMenu(MenuBar) + var TopMenu = menuBarNew() + + # FileMenu + var FileMenu = menuNew() + + var NewMenuItem = menu_item_new("New") # New + FileMenu.append(NewMenuItem) + show(NewMenuItem) + discard signal_connect(NewMenuItem, "activate", + SIGNAL_FUNC(newFile), nil) + + createSeparator(FileMenu) + + var OpenMenuItem = menu_item_new("Open...") # Open... + # CTRL + O + OpenMenuItem.add_accelerator("activate", accGroup, + KEY_o, CONTROL_MASK, ACCEL_VISIBLE) + FileMenu.append(OpenMenuItem) + show(OpenMenuItem) + discard signal_connect(OpenMenuItem, "activate", + SIGNAL_FUNC(aporia.openFile), nil) + + var SaveMenuItem = menu_item_new("Save") # Save + # CTRL + S + SaveMenuItem.add_accelerator("activate", accGroup, + KEY_s, CONTROL_MASK, ACCEL_VISIBLE) + FileMenu.append(SaveMenuItem) + show(SaveMenuItem) + discard signal_connect(SaveMenuItem, "activate", + SIGNAL_FUNC(saveFile_activate), nil) + + var SaveAsMenuItem = menu_item_new("Save As...") # Save as... + + SaveAsMenuItem.add_accelerator("activate", accGroup, + KEY_s, CONTROL_MASK or gdk2.SHIFT_MASK, ACCEL_VISIBLE) + FileMenu.append(SaveAsMenuItem) + show(SaveAsMenuItem) + discard signal_connect(SaveAsMenuItem, "activate", + SIGNAL_FUNC(saveFileAs_Activate), nil) + + var FileMenuItem = menuItemNewWithMnemonic("_File") + + FileMenuItem.setSubMenu(FileMenu) + FileMenuItem.show() + TopMenu.append(FileMenuItem) + + # Edit menu + var EditMenu = menuNew() + + var UndoMenuItem = menu_item_new("Undo") # Undo + EditMenu.append(UndoMenuItem) + show(UndoMenuItem) + discard signal_connect(UndoMenuItem, "activate", + SIGNAL_FUNC(aporia.undo), nil) + + var RedoMenuItem = menu_item_new("Redo") # Undo + EditMenu.append(RedoMenuItem) + show(RedoMenuItem) + discard signal_connect(RedoMenuItem, "activate", + SIGNAL_FUNC(aporia.redo), nil) + + createSeparator(EditMenu) + + var FindMenuItem = menu_item_new("Find") # Find + FindMenuItem.add_accelerator("activate", accGroup, + KEY_f, CONTROL_MASK, ACCEL_VISIBLE) + EditMenu.append(FindMenuItem) + show(FindMenuItem) + discard signal_connect(FindMenuItem, "activate", + SIGNAL_FUNC(aporia.find_Activate), nil) + + var ReplaceMenuItem = menu_item_new("Replace") # Replace + ReplaceMenuItem.add_accelerator("activate", accGroup, + KEY_h, CONTROL_MASK, ACCEL_VISIBLE) + EditMenu.append(ReplaceMenuItem) + show(ReplaceMenuItem) + discard signal_connect(ReplaceMenuItem, "activate", + SIGNAL_FUNC(aporia.replace_Activate), nil) + + createSeparator(EditMenu) + + var SettingsMenuItem = menu_item_new("Settings...") # Settings + EditMenu.append(SettingsMenuItem) + show(SettingsMenuItem) + discard signal_connect(SettingsMenuItem, "activate", + SIGNAL_FUNC(aporia.Settings_Activate), nil) + + var EditMenuItem = menuItemNewWithMnemonic("_Edit") + + EditMenuItem.setSubMenu(EditMenu) + EditMenuItem.show() + TopMenu.append(EditMenuItem) + + # View menu + var ViewMenu = menuNew() + + win.viewBottomPanelMenuItem = check_menu_item_new("Bottom Panel") + PCheckMenuItem(win.viewBottomPanelMenuItem).itemSetActive( + win.settings.bottomPanelVisible) + win.viewBottomPanelMenuItem.add_accelerator("activate", accGroup, + KEY_f9, CONTROL_MASK, ACCEL_VISIBLE) + ViewMenu.append(win.viewBottomPanelMenuItem) + show(win.viewBottomPanelMenuItem) + discard signal_connect(win.viewBottomPanelMenuItem, "toggled", + SIGNAL_FUNC(aporia.viewBottomPanel_Toggled), nil) + + var ViewMenuItem = menuItemNewWithMnemonic("_View") + + ViewMenuItem.setSubMenu(ViewMenu) + ViewMenuItem.show() + TopMenu.append(ViewMenuItem) + + + # Tools menu + var ToolsMenu = menuNew() + + createAccelMenuItem(ToolsMenu, accGroup, "Compile current file", + KEY_F4, aporia.CompileCurrent_Activate) + createAccelMenuItem(ToolsMenu, accGroup, "Compile & run current file", + KEY_F5, aporia.CompileRunCurrent_Activate) + createSeparator(ToolsMenu) + createAccelMenuItem(ToolsMenu, accGroup, "Compile project", + KEY_F8, aporia.CompileProject_Activate) + createAccelMenuItem(ToolsMenu, accGroup, "Compile & run project", + KEY_F9, aporia.CompileRunProject_Activate) + createSeparator(ToolsMenu) + createAccelMenuItem(ToolsMenu, accGroup, "Run custom command 1", + KEY_F1, aporia.RunCustomCommand1) + createAccelMenuItem(ToolsMenu, accGroup, "Run custom command 2", + KEY_F2, aporia.RunCustomCommand2) + createAccelMenuItem(ToolsMenu, accGroup, "Run custom command 3", + KEY_F3, aporia.RunCustomCommand3) + + var ToolsMenuItem = menuItemNewWithMnemonic("_Tools") + + ToolsMenuItem.setSubMenu(ToolsMenu) + ToolsMenuItem.show() + TopMenu.append(ToolsMenuItem) + + # Help menu + MainBox.packStart(TopMenu, False, False, 0) + TopMenu.show() + +proc initToolBar(MainBox: PBox) = + # TopBar(ToolBar) + var TopBar = toolbarNew() + TopBar.setStyle(TOOLBAR_ICONS) + + var NewFileItem = TopBar.insertStock(STOCK_NEW, "New File", + "New File", SIGNAL_FUNC(aporia.newFile), nil, 0) + TopBar.appendSpace() + var OpenItem = TopBar.insertStock(STOCK_OPEN, "Open", + "Open", SIGNAL_FUNC(aporia.openFile), nil, -1) + var SaveItem = TopBar.insertStock(STOCK_SAVE, "Save", + "Save", SIGNAL_FUNC(saveFile_Activate), nil, -1) + TopBar.appendSpace() + var UndoItem = TopBar.insertStock(STOCK_UNDO, "Undo", + "Undo", SIGNAL_FUNC(aporia.undo), nil, -1) + var RedoItem = TopBar.insertStock(STOCK_REDO, "Redo", + "Redo", SIGNAL_FUNC(aporia.redo), nil, -1) + + MainBox.packStart(TopBar, False, False, 0) + TopBar.show() + +proc initSourceViewTabs() = + win.SourceViewTabs = notebookNew() + #win.sourceViewTabs.dragDestSet(DEST_DEFAULT_DROP, nil, 0, ACTION_MOVE) + discard win.SourceViewTabs.signalConnect( + "switch-page", SIGNAL_FUNC(onSwitchTab), nil) + #discard win.SourceViewTabs.signalConnect( + # "drag-drop", SIGNAL_FUNC(svTabs_DragDrop), nil) + #discard win.SourceViewTabs.signalConnect( + # "drag-data-received", SIGNAL_FUNC(svTabs_DragDataRecv), nil) + #discard win.SourceViewTabs.signalConnect( + # "drag-motion", SIGNAL_FUNC(svTabs_DragMotion), nil) + win.SourceViewTabs.set_scrollable(True) + + win.SourceViewTabs.show() + if lastSession.len != 0: + for i in 0 .. len(lastSession)-1: + var splitUp = lastSession[i].split('|') + var (filename, offset) = (splitUp[0], splitUp[1]) + addTab("", filename) + + var iter: TTextIter + win.Tabs[i].buffer.getIterAtOffset(addr(iter), offset.parseInt()) + win.Tabs[i].buffer.moveMarkByName("insert", addr(iter)) + win.Tabs[i].buffer.moveMarkByName("selection_bound", addr(iter)) + + # TODO: Fix this..... :( + discard PTextView(win.Tabs[i].sourceView). + scrollToIter(addr(iter), 0.25, true, 0.0, 0.0) + else: + addTab("", "") + + # This doesn't work :\ + win.Tabs[0].sourceView.grabFocus() + + +proc initBottomTabs() = + win.bottomPanelTabs = notebookNew() + if win.settings.bottomPanelVisible: + win.bottomPanelTabs.show() + + # output tab + var tabLabel = labelNew("Output") + var outputTab = vboxNew(False, 0) + discard win.bottomPanelTabs.appendPage(outputTab, tabLabel) + # Compiler tabs, gtktextview + var outputScrolledWindow = scrolledwindowNew(nil, nil) + outputScrolledWindow.setPolicy(POLICY_AUTOMATIC, POLICY_AUTOMATIC) + outputTab.packStart(outputScrolledWindow, true, true, 0) + outputScrolledWindow.show() + + win.outputTextView = textviewNew() + outputScrolledWindow.add(win.outputTextView) + win.outputTextView.show() + + outputTab.show() + +proc initTAndBP(MainBox: PBox) = + # This init's the HPaned, which splits the sourceViewTabs + # and the BottomPanelTabs + initSourceViewTabs() + initBottomTabs() + + var TAndBPVPaned = vpanedNew() + tandbpVPaned.pack1(win.sourceViewTabs, resize=True, shrink=False) + tandbpVPaned.pack2(win.bottomPanelTabs, resize=False, shrink=False) + MainBox.packStart(TAndBPVPaned, True, True, 0) + tandbpVPaned.setPosition(win.settings.VPanedPos) + TAndBPVPaned.show() + +proc initFindBar(MainBox: PBox) = + # Create a fixed container + win.findBar = HBoxNew(False, 0) + win.findBar.setSpacing(4) + + # Add a Label 'Find' + var findLabel = labelNew("Find:") + win.findBar.packStart(findLabel, False, False, 0) + findLabel.show() + + # Add a (find) text entry + win.findEntry = entryNew() + win.findBar.packStart(win.findEntry, False, False, 0) + discard win.findEntry.signalConnect("activate", SIGNAL_FUNC( + aporia.nextBtn_Clicked), nil) + win.findEntry.show() + var rq: TRequisition + win.findEntry.sizeRequest(addr(rq)) + + # Make the (find) text entry longer + win.findEntry.set_size_request(190, rq.height) + + # Add a Label 'Replace' + # - This Is only shown, when the 'Search & Replace'(CTRL + H) is shown + win.replaceLabel = labelNew("Replace:") + win.findBar.packStart(win.replaceLabel, False, False, 0) + #replaceLabel.show() + + # Add a (replace) text entry + # - This Is only shown, when the 'Search & Replace'(CTRL + H) is shown + win.replaceEntry = entryNew() + win.findBar.packStart(win.replaceEntry, False, False, 0) + #win.replaceEntry.show() + var rq1: TRequisition + win.replaceEntry.sizeRequest(addr(rq1)) + + # Make the (replace) text entry longer + win.replaceEntry.set_size_request(100, rq1.height) + + # Find next button + var nextBtn = buttonNew("Next") + win.findBar.packStart(nextBtn, false, false, 0) + discard nextBtn.signalConnect("clicked", + SIGNAL_FUNC(aporia.nextBtn_Clicked), nil) + nextBtn.show() + var nxtBtnRq: TRequisition + nextBtn.sizeRequest(addr(nxtBtnRq)) + + # Find previous button + var prevBtn = buttonNew("Previous") + win.findBar.packStart(prevBtn, false, false, 0) + discard prevBtn.signalConnect("clicked", + SIGNAL_FUNC(aporia.prevBtn_Clicked), nil) + prevBtn.show() + + # Replace button + # - This Is only shown, when the 'Search & Replace'(CTRL + H) is shown + win.replaceBtn = buttonNew("Replace") + win.findBar.packStart(win.replaceBtn, false, false, 0) + discard win.replaceBtn.signalConnect("clicked", + SIGNAL_FUNC(aporia.replaceBtn_Clicked), nil) + #replaceBtn.show() + + # Replace all button + # - this Is only shown, when the 'Search & Replace'(CTRL + H) is shown + win.replaceAllBtn = buttonNew("Replace All") + win.findBar.packStart(win.replaceAllBtn, false, false, 0) + discard win.replaceAllBtn.signalConnect("clicked", + SIGNAL_FUNC(aporia.replaceAllBtn_Clicked), nil) + #replaceAllBtn.show() + + # Right side ... + + # Close button - With a close stock image + var closeBtn = buttonNew() + var closeImage = imageNewFromStock(STOCK_CLOSE, ICON_SIZE_SMALL_TOOLBAR) + var closeBox = hboxNew(False, 0) + closeBtn.add(closeBox) + closeBox.show() + closeBox.add(closeImage) + closeImage.show() + discard closeBtn.signalConnect("clicked", + SIGNAL_FUNC(aporia.closeBtn_Clicked), nil) + win.findBar.packEnd(closeBtn, False, False, 2) + closeBtn.show() + + # Extra button - When clicked shows a menu with options like 'Use regex' + var extraBtn = buttonNew() + var extraImage = imageNewFromStock(STOCK_PROPERTIES, ICON_SIZE_SMALL_TOOLBAR) + + var extraBox = hboxNew(False, 0) + extraBtn.add(extraBox) + extraBox.show() + extraBox.add(extraImage) + extraImage.show() + discard extraBtn.signalConnect("clicked", + SIGNAL_FUNC(aporia.extraBtn_Clicked), nil) + win.findBar.packEnd(extraBtn, False, False, 0) + extraBtn.show() + + MainBox.packStart(win.findBar, False, False, 0) + win.findBar.show() + +proc initStatusBar(MainBox: PBox) = + win.bottomBar = statusbarNew() + MainBox.packStart(win.bottomBar, False, False, 0) + win.bottomBar.show() + + discard win.bottomBar.push(0, "Line: 0 Column: 0") + +proc initControls() = + # Load up the language style + win.langMan = languageManagerGetDefault() + var langpaths: array[0..1, cstring] = + [cstring(os.getApplicationDir() / langSpecs), nil] + win.langMan.setSearchPath(addr(langpaths)) + var nimLang = win.langMan.getLanguage("nimrod") + win.nimLang = nimLang + + # Load the scheme + var schemeMan = schemeManagerGetDefault() + var schemepaths: array[0..1, cstring] = + [cstring(os.getApplicationDir() / styles), nil] + schemeMan.setSearchPath(addr(schemepaths)) + win.scheme = schemeMan.getScheme(win.settings.colorSchemeID) + + # Window + win.w = windowNew(gtk2.WINDOW_TOPLEVEL) + win.w.setDefaultSize(win.settings.winWidth, win.settings.winHeight) + win.w.setTitle("Aporia IDE") + if win.settings.winMaximized: win.w.maximize() + + win.w.show() # The window has to be shown before + # setting the position of the VPaned so that + # it gets set correctly, when the window is maximized. + + discard win.w.signalConnect("destroy", SIGNAL_FUNC(aporia.destroy), nil) + discard win.w.signalConnect("delete_event", + SIGNAL_FUNC(aporia.delete_event), nil) + discard win.w.signalConnect("window-state-event", + SIGNAL_FUNC(aporia.windowState_Changed), nil) + + # MainBox (vbox) + var MainBox = vboxNew(False, 0) + win.w.add(MainBox) + + initTopMenu(MainBox) + initToolBar(MainBox) + initTAndBP(MainBox) + initFindBar(MainBox) + initStatusBar(MainBox) + + MainBox.show() + if confParseFail: + dialogs.warning(win.w, "Error parsing config file, using default settings.") + +nimrod_init() +initControls() +main() + |