1 module dlangide.ui.frame; 2 3 import dlangui.widgets.menu; 4 import dlangui.widgets.tabs; 5 import dlangui.widgets.layouts; 6 import dlangui.widgets.editors; 7 import dlangui.widgets.srcedit; 8 import dlangui.widgets.controls; 9 import dlangui.widgets.appframe; 10 import dlangui.widgets.docks; 11 import dlangui.widgets.toolbars; 12 import dlangui.dialogs.dialog; 13 import dlangui.dialogs.filedlg; 14 15 import dlangide.ui.commands; 16 import dlangide.ui.wspanel; 17 import dlangide.ui.outputpanel; 18 import dlangide.workspace.workspace; 19 import dlangide.workspace.project; 20 21 import ddc.lexer.textsource; 22 import ddc.lexer.exceptions; 23 import ddc.lexer.tokenizer; 24 25 import std.conv; 26 import std.utf; 27 import std.algorithm; 28 29 /// DIDE app frame 30 class IDEFrame : AppFrame { 31 32 MenuItem mainMenuItems; 33 WorkspacePanel _wsPanel; 34 OutputPanel _logPanel; 35 DockHost _dockHost; 36 TabWidget _tabs; 37 38 this(Window window) { 39 super(); 40 window.mainWidget = this; 41 } 42 43 override protected void init() { 44 super.init(); 45 } 46 47 /// move focus to editor in currently selected tab 48 void focusEditor(string id) { 49 Widget w = _tabs.tabBody(id); 50 if (w) { 51 if (w.visible) 52 w.setFocus(); 53 } 54 } 55 56 /// source file selected in workspace tree 57 bool onSourceFileSelected(ProjectSourceFile file, bool activate) { 58 Log.d("onSourceFileSelected ", file.filename); 59 int index = _tabs.tabIndex(file.filename); 60 if (index >= 0) { 61 // file is already opened in tab 62 _tabs.selectTab(index, true); 63 } else { 64 // open new file 65 DSourceEdit editor = new DSourceEdit(file.filename); 66 if (editor.load(file)) { 67 _tabs.addTab(editor, toUTF32(file.name)); 68 index = _tabs.tabIndex(file.filename); 69 TabItem tab = _tabs.tab(file.filename); 70 tab.objectParam = file; 71 _tabs.selectTab(index, true); 72 } else { 73 destroy(editor); 74 if (window) 75 window.showMessageBox(UIString("File open error"d), UIString("Failed to open file "d ~ toUTF32(file.filename))); 76 return false; 77 } 78 } 79 if (activate) { 80 focusEditor(file.filename); 81 } 82 requestLayout(); 83 return true; 84 } 85 86 void onTabChanged(string newActiveTabId, string previousTabId) { 87 int index = _tabs.tabIndex(newActiveTabId); 88 if (index >= 0) { 89 TabItem tab = _tabs.tab(index); 90 ProjectSourceFile file = cast(ProjectSourceFile)tab.objectParam; 91 if (file) { 92 // tab is source file editor 93 _wsPanel.selectItem(file); 94 focusEditor(file.filename); 95 } 96 } 97 } 98 99 /// create app body widget 100 override protected Widget createBody() { 101 _dockHost = new DockHost(); 102 103 //============================================================= 104 // Create body - Tabs 105 106 // editor tabs 107 _tabs = new TabWidget("TABS"); 108 _tabs.setStyles(STYLE_DOCK_HOST_BODY, STYLE_TAB_UP_DARK, STYLE_TAB_UP_BUTTON_DARK, STYLE_TAB_UP_BUTTON_DARK_TEXT); 109 _tabs.onTabChangedListener = &onTabChanged; 110 111 _dockHost.bodyWidget = _tabs; 112 113 //============================================================= 114 // Create workspace docked panel 115 _wsPanel = new WorkspacePanel("workspace"); 116 _wsPanel.sourceFileSelectionListener = &onSourceFileSelected; 117 _dockHost.addDockedWindow(_wsPanel); 118 119 _logPanel = new OutputPanel("output"); 120 _logPanel.addLogLines(null, "Line 1"d); 121 _logPanel.addLogLines(null, "Line 2"d); 122 _logPanel.addLogLines(null, "Line 3"d, "Line 4"d); 123 124 _dockHost.addDockedWindow(_logPanel); 125 126 return _dockHost; 127 } 128 129 /// create main menu 130 override protected MainMenu createMainMenu() { 131 132 mainMenuItems = new MenuItem(); 133 MenuItem fileItem = new MenuItem(new Action(1, "MENU_FILE")); 134 fileItem.add(ACTION_FILE_NEW, ACTION_FILE_OPEN, ACTION_FILE_SAVE, ACTION_FILE_EXIT); 135 136 MenuItem editItem = new MenuItem(new Action(2, "MENU_EDIT")); 137 editItem.add(ACTION_EDIT_COPY, ACTION_EDIT_PASTE, ACTION_EDIT_CUT, ACTION_EDIT_UNDO, ACTION_EDIT_REDO); 138 139 editItem.add(new Action(20, "MENU_EDIT_PREFERENCES")); 140 MenuItem windowItem = new MenuItem(new Action(3, "MENU_WINDOW"c)); 141 windowItem.add(new Action(30, "MENU_WINDOW_PREFERENCES")); 142 MenuItem helpItem = new MenuItem(new Action(4, "MENU_HELP"c)); 143 helpItem.add(new Action(40, "MENU_HELP_VIEW_HELP")); 144 MenuItem aboutItem = new MenuItem(new Action(ACTION_HELP_ABOUT, "MENU_HELP_ABOUT")); 145 helpItem.add(aboutItem); 146 aboutItem.onMenuItemClick = delegate(MenuItem item) { 147 Window wnd = Platform.instance.createWindow("About...", window, WindowFlag.Modal); 148 wnd.mainWidget = createAboutWidget(); 149 wnd.show(); 150 return true; 151 }; 152 mainMenuItems.add(fileItem); 153 mainMenuItems.add(editItem); 154 //mainMenuItems.add(viewItem); 155 mainMenuItems.add(windowItem); 156 mainMenuItems.add(helpItem); 157 158 MainMenu mainMenu = new MainMenu(mainMenuItems); 159 mainMenu.backgroundColor = 0xd6dbe9; 160 return mainMenu; 161 } 162 163 /// create app toolbars 164 override protected ToolBarHost createToolbars() { 165 ToolBarHost res = new ToolBarHost(); 166 ToolBar tb; 167 tb = res.getOrAddToolbar("Standard"); 168 tb.addButtons(ACTION_FILE_OPEN, ACTION_FILE_SAVE, ACTION_SEPARATOR, 169 ACTION_EDIT_COPY, ACTION_EDIT_PASTE, ACTION_EDIT_CUT); 170 return res; 171 } 172 173 /// override to handle specific actions 174 override bool handleAction(const Action a) { 175 if (a) { 176 switch (a.id) { 177 case IDEActions.FileExit: 178 return true; 179 case ACTION_HELP_ABOUT: 180 Window wnd = Platform.instance.createWindow("About...", window, WindowFlag.Modal); 181 wnd.mainWidget = createAboutWidget(); 182 wnd.show(); 183 return true; 184 case IDEActions.FileOpen: 185 UIString caption; 186 caption = "Open Text File"d; 187 FileDialog dlg = new FileDialog(caption, window, null); 188 dlg.onDialogResult = delegate(Dialog dlg, const Action result) { 189 // 190 }; 191 dlg.show(); 192 return true; 193 default: 194 if (window.focusedWidget) 195 return window.focusedWidget.handleAction(a); 196 else 197 return handleAction(a); 198 } 199 } 200 return false; 201 } 202 203 bool loadWorkspace(string path) { 204 // testing workspace loader 205 Workspace ws = new Workspace(); 206 ws.load(path); 207 currentWorkspace = ws; 208 _wsPanel.workspace = ws; 209 return true; 210 } 211 } 212 213 Widget createAboutWidget() 214 { 215 LinearLayout res = new VerticalLayout(); 216 res.padding(Rect(10,10,10,10)); 217 res.addChild(new TextWidget(null, "DLangIDE"d)); 218 res.addChild(new TextWidget(null, "(C) Vadim Lopatin, 2014"d)); 219 res.addChild(new TextWidget(null, "http://github.com/buggins/dlangide"d)); 220 res.addChild(new TextWidget(null, "So far, it's just a test for DLangUI library."d)); 221 res.addChild(new TextWidget(null, "Later I hope to make working IDE :)"d)); 222 Button closeButton = new Button("close", "Close"d); 223 closeButton.onClickListener = delegate(Widget src) { 224 Log.i("Closing window"); 225 res.window.close(); 226 return true; 227 }; 228 res.addChild(closeButton); 229 return res; 230 }