1 module spreadsheet;
2 
3 import dlangui;
4 import dlangui.dialogs.filedlg;
5 import dlangui.dialogs.dialog;
6 import dlangui.widgets.spreadsheet;
7 import std.array : replaceFirst;
8 
9 mixin APP_ENTRY_POINT;
10 
11 // action codes
12 enum IDEActions : int {
13     //ProjectOpen = 1010000,
14     FileNew = 1010000,
15     FileOpen,
16     FileSave,
17     FileSaveAs,
18     FileSaveAll,
19     FileClose,
20     FileExit,
21     EditPreferences,
22     DebugStart,
23     HelpAbout,
24 }
25 
26 // actions
27 const Action ACTION_FILE_NEW = new Action(IDEActions.FileNew, "MENU_FILE_NEW"c, "document-new", KeyCode.KEY_N, KeyFlag.Control);
28 const Action ACTION_FILE_SAVE = (new Action(IDEActions.FileSave, "MENU_FILE_SAVE"c, "document-save", KeyCode.KEY_S, KeyFlag.Control)).disableByDefault();
29 const Action ACTION_FILE_SAVE_AS = (new Action(IDEActions.FileSaveAs, "MENU_FILE_SAVE_AS"c)).disableByDefault();
30 const Action ACTION_FILE_OPEN = new Action(IDEActions.FileOpen, "MENU_FILE_OPEN"c, "document-open", KeyCode.KEY_O, KeyFlag.Control);
31 const Action ACTION_FILE_EXIT = new Action(IDEActions.FileExit, "MENU_FILE_EXIT"c, "document-close"c, KeyCode.KEY_X, KeyFlag.Alt);
32 const Action ACTION_EDIT_COPY = (new Action(EditorActions.Copy, "MENU_EDIT_COPY"c, "edit-copy"c, KeyCode.KEY_C, KeyFlag.Control)).addAccelerator(KeyCode.INS, KeyFlag.Control).disableByDefault();
33 const Action ACTION_EDIT_PASTE = (new Action(EditorActions.Paste, "MENU_EDIT_PASTE"c, "edit-paste"c, KeyCode.KEY_V, KeyFlag.Control)).addAccelerator(KeyCode.INS, KeyFlag.Shift).disableByDefault();
34 const Action ACTION_EDIT_CUT = (new Action(EditorActions.Cut, "MENU_EDIT_CUT"c, "edit-cut"c, KeyCode.KEY_X, KeyFlag.Control)).addAccelerator(KeyCode.DEL, KeyFlag.Shift).disableByDefault();
35 const Action ACTION_EDIT_UNDO = (new Action(EditorActions.Undo, "MENU_EDIT_UNDO"c, "edit-undo"c, KeyCode.KEY_Z, KeyFlag.Control)).disableByDefault();
36 const Action ACTION_EDIT_REDO = (new Action(EditorActions.Redo, "MENU_EDIT_REDO"c, "edit-redo"c, KeyCode.KEY_Y, KeyFlag.Control)).addAccelerator(KeyCode.KEY_Z, KeyFlag.Control|KeyFlag.Shift).disableByDefault();
37 const Action ACTION_EDIT_INDENT = (new Action(EditorActions.Indent, "MENU_EDIT_INDENT"c, "edit-indent"c, KeyCode.TAB, 0)).addAccelerator(KeyCode.KEY_BRACKETCLOSE, KeyFlag.Control).disableByDefault();
38 const Action ACTION_EDIT_UNINDENT = (new Action(EditorActions.Unindent, "MENU_EDIT_UNINDENT"c, "edit-unindent", KeyCode.TAB, KeyFlag.Shift)).addAccelerator(KeyCode.KEY_BRACKETOPEN, KeyFlag.Control).disableByDefault();
39 const Action ACTION_EDIT_TOGGLE_LINE_COMMENT = (new Action(EditorActions.ToggleLineComment, "MENU_EDIT_TOGGLE_LINE_COMMENT"c, null, KeyCode.KEY_DIVIDE, KeyFlag.Control)).disableByDefault();
40 const Action ACTION_EDIT_TOGGLE_BLOCK_COMMENT = (new Action(EditorActions.ToggleBlockComment, "MENU_EDIT_TOGGLE_BLOCK_COMMENT"c, null, KeyCode.KEY_DIVIDE, KeyFlag.Control|KeyFlag.Shift)).disableByDefault();
41 const Action ACTION_EDIT_PREFERENCES = (new Action(IDEActions.EditPreferences, "MENU_EDIT_PREFERENCES"c, null)).disableByDefault();
42 const Action ACTION_DEBUG_START = new Action(IDEActions.DebugStart, "MENU_DEBUG_UPDATE_PREVIEW"c, "debug-run"c, KeyCode.F5, 0);
43 const Action ACTION_HELP_ABOUT = new Action(IDEActions.HelpAbout, "MENU_HELP_ABOUT"c);
44 
45 class EditFrame : AppFrame {
46 
47     MenuItem mainMenuItems;
48 
49     override protected void initialize() {
50         _appName = "DlangUISpreadSheet";
51         super.initialize();
52     }
53 
54     /// create main menu
55     override protected MainMenu createMainMenu() {
56         mainMenuItems = new MenuItem();
57         MenuItem fileItem = new MenuItem(new Action(1, "MENU_FILE"));
58         fileItem.add(ACTION_FILE_NEW, ACTION_FILE_OPEN,
59                      ACTION_FILE_EXIT);
60         mainMenuItems.add(fileItem);
61         MenuItem editItem = new MenuItem(new Action(2, "MENU_EDIT"));
62         editItem.add(ACTION_EDIT_COPY, ACTION_EDIT_PASTE,
63                      ACTION_EDIT_CUT, ACTION_EDIT_UNDO, ACTION_EDIT_REDO,
64                      ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT, ACTION_EDIT_TOGGLE_LINE_COMMENT, ACTION_EDIT_TOGGLE_BLOCK_COMMENT, ACTION_DEBUG_START);
65 
66         editItem.add(ACTION_EDIT_PREFERENCES);
67         mainMenuItems.add(editItem);
68         MainMenu mainMenu = new MainMenu(mainMenuItems);
69         return mainMenu;
70     }
71 
72 
73     /// create app toolbars
74     override protected ToolBarHost createToolbars() {
75         ToolBarHost res = new ToolBarHost();
76         ToolBar tb;
77         tb = res.getOrAddToolbar("Standard");
78         tb.addButtons(ACTION_FILE_NEW, ACTION_FILE_OPEN, ACTION_FILE_SAVE, ACTION_SEPARATOR, ACTION_DEBUG_START);
79 
80         tb = res.getOrAddToolbar("Edit");
81         tb.addButtons(ACTION_EDIT_COPY, ACTION_EDIT_PASTE, ACTION_EDIT_CUT, ACTION_SEPARATOR,
82                       ACTION_EDIT_UNDO, ACTION_EDIT_REDO, ACTION_EDIT_INDENT, ACTION_EDIT_UNINDENT);
83         return res;
84     }
85 
86     string _filename;
87     void openSourceFile(string filename) {
88         import std.file;
89         // TODO
90         if (exists(filename)) {
91             _filename = filename;
92             window.windowCaption = toUTF32(filename);
93             //_editor.load(filename);
94             //updatePreview();
95         }
96     }
97 
98     void saveSourceFile(string filename) {
99         if (filename.length == 0)
100             filename = _filename;
101         //import std.file;
102         //_filename = filename;
103         //window.windowCaption = toUTF32(filename);
104         //_editor.save(filename);
105     }
106 
107     bool onCanClose() {
108         // todo
109         return true;
110     }
111 
112     FileDialog createFileDialog(UIString caption, bool fileMustExist = true) {
113         uint flags = DialogFlag.Modal | DialogFlag.Resizable;
114         if (fileMustExist)
115             flags |= FileDialogFlag.FileMustExist;
116         FileDialog dlg = new FileDialog(caption, window, null, flags);
117         dlg.filetypeIcons[".d"] = "text-dml";
118         return dlg;
119     }
120 
121     void saveAs() {
122     }
123 
124     /// override to handle specific actions
125     override bool handleAction(const Action a) {
126         if (a) {
127             switch (a.id) {
128                 case IDEActions.FileExit:
129                     if (onCanClose())
130                         window.close();
131                     return true;
132                 case IDEActions.HelpAbout:
133                     window.showMessageBox(UIString.fromRaw("About DlangUI ML Editor"d),
134                                           UIString.fromRaw("DLangIDE\n(C) Vadim Lopatin, 2015\nhttp://github.com/buggins/dlangui\nSimple editor for DML code"d));
135                     return true;
136                 case IDEActions.FileNew:
137                     UIString caption;
138                     caption = "Create new DML file"d;
139                     FileDialog dlg = createFileDialog(caption, false);
140                     dlg.addFilter(FileFilterEntry(UIString.fromRaw("DML files"d), "*.dml"));
141                     dlg.addFilter(FileFilterEntry(UIString.fromRaw("All files"d), "*.*"));
142                     dlg.dialogResult = delegate(Dialog dlg, const Action result) {
143                         if (result.id == ACTION_OPEN.id) {
144                             string filename = result.stringParam;
145                             //_editor.text=""d;
146                             saveSourceFile(filename);
147                         }
148                     };
149                     dlg.show();
150                     return true;
151                 case IDEActions.FileSave:
152                     if (_filename.length) {
153                         saveSourceFile(_filename);
154                         return true;
155                     }
156                     UIString caption;
157                     caption = "Save DML File as"d;
158                     FileDialog dlg = createFileDialog(caption, false);
159                     dlg.addFilter(FileFilterEntry(UIString.fromRaw("DML files"d), "*.dml"));
160                     dlg.addFilter(FileFilterEntry(UIString.fromRaw("All files"d), "*.*"));
161                     dlg.dialogResult = delegate(Dialog dlg, const Action result) {
162                         if (result.id == ACTION_OPEN.id) {
163                             string filename = result.stringParam;
164                             saveSourceFile(filename);
165                         }
166                     };
167                     dlg.show();
168                     return true;
169                 case IDEActions.FileOpen:
170                     UIString caption;
171                     caption = "Open DML File"d;
172                     FileDialog dlg = createFileDialog(caption);
173                     dlg.addFilter(FileFilterEntry(UIString.fromRaw("DML files"d), "*.dml"));
174                     dlg.addFilter(FileFilterEntry(UIString.fromRaw("All files"d), "*.*"));
175                     dlg.dialogResult = delegate(Dialog dlg, const Action result) {
176                         if (result.id == ACTION_OPEN.id) {
177                             string filename = result.stringParam;
178                             openSourceFile(filename);
179                         }
180                     };
181                     dlg.show();
182                     return true;
183                 case IDEActions.DebugStart:
184                     return true;
185                 case IDEActions.EditPreferences:
186                     //showPreferences();
187                     return true;
188                 default:
189                     return super.handleAction(a);
190             }
191         }
192         return false;
193     }
194 
195     /// override to handle specific actions state (e.g. change enabled state for supported actions)
196     override bool handleActionStateRequest(const Action a) {
197         switch (a.id) {
198             case IDEActions.HelpAbout:
199             case IDEActions.FileNew:
200             case IDEActions.FileSave:
201             case IDEActions.FileOpen:
202             case IDEActions.DebugStart:
203             case IDEActions.EditPreferences:
204                 a.state = ACTION_STATE_ENABLED;
205                 return true;
206             default:
207                 return super.handleActionStateRequest(a);
208         }
209     }
210 
211     SpreadSheetWidget _spreadsheet;
212 
213     /// create app body widget
214     override protected Widget createBody() {
215         VerticalLayout bodyWidget = new VerticalLayout();
216         bodyWidget.layoutWidth = FILL_PARENT;
217         bodyWidget.layoutHeight = FILL_PARENT;
218         _spreadsheet = new SpreadSheetWidget();
219         bodyWidget.addChild(_spreadsheet);
220         return bodyWidget;
221     }
222 
223 }
224 
225 /// entry point for dlangui based application
226 extern (C) int UIAppMain(string[] args) {
227 
228     // embed non-standard resources listed in views/resources.list into executable
229     embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
230 
231     /// set font gamma (1.0 is neutral, < 1.0 makes glyphs lighter, >1.0 makes glyphs bolder)
232     FontManager.fontGamma = 0.8;
233     FontManager.hintingMode = HintingMode.Normal;
234 
235     // select translation file - for english language
236     Platform.instance.uiLanguage = "en";
237     // load theme from file "theme_custom.xml"
238     Platform.instance.uiTheme = "theme_custom";
239 
240     // create window
241     Window window = Platform.instance.createWindow("DlangUI SpreadSheet example"d, null, WindowFlag.Resizable, 700, 470);
242 
243     // create some widget to show in window
244     window.windowIcon = drawableCache.getImage("dlangui-logo1");
245 
246     FontRef font = FontManager.instance.getFont(24, 300, false, FontFamily.SansSerif, "Arial");
247     Log.d("font found: ", font.face);
248     font = FontManager.instance.getFont(24, 300, false, FontFamily.Serif, "Times New Roman");
249     Log.d("font found: ", font.face);
250 
251     // create some widget to show in window
252     window.mainWidget = new EditFrame();
253 
254     // show window
255     window.show();
256 
257     // run message loop
258     return Platform.instance.enterMessageLoop();
259 }