MainWindow.setMenuAndToolbarFromAnnotatedCode

Adds a menu and toolbar from annotated functions. It uses the top-level annotations from this module, so it is better to put the commands in a separate struct instad of in your window subclass, to avoid potential conflicts with method names (if you do hit one though, you can use @(.icon(...)) instead of plain @icon(...) to disambiguate, though).

The only required annotation on a function is @menu("Label") to make it appear, but there are several optional ones I'd recommend considering, including @toolbar("group name"), @icon(), @accelerator("keyboard shortcut string"), and @hotkey('char').

You can also use @separator to put a separating line in the menu before the function.

Functions may have zero or one argument. If they have an argument, an automatic dialog box (see: dialog) will be created to request the data from the user before calling your function. Some types have special treatment, like FileName, will invoke the file dialog, assuming open or save based on the name of your function.

Let's look at a complete example:

1 import arsd.minigui;
2 
3 void main() {
4 	auto window = new MainWindow();
5 
6 	// we can add widgets before or after setting the menu, either way is fine.
7 	// i'll do it before here so the local variables are available to the commands.
8 
9 	auto textEdit = new TextEdit(window);
10 
11 	// Remember, in D, you can define structs inside of functions
12 	// and those structs can access the function's local variables.
13 	//
14 	// Of course, you might also want to do this separately, and if you
15 	// do, make sure you keep a reference to the window as a struct data
16 	// member so you can refer to it in cases like this Exit function.
17 	struct Commands {
18 		// the & in the string indicates that the next letter is the hotkey
19 		// to access it from the keyboard (so here, alt+f will open the
20 		// file menu)
21 		@menu("&File") {
22 			@accelerator("Ctrl+N")
23 			@hotkey('n')
24 			@icon(GenericIcons.New) // add an icon to the action
25 			@toolbar("File") // adds it to a toolbar.
26 			// The toolbar name is never visible to the user, but is used to group icons.
27 			void New() {
28 				previousFileReferenced = null;
29 				textEdit.content = "";
30 			}
31 
32 			@icon(GenericIcons.Open)
33 			@toolbar("File")
34 			@hotkey('s')
35 			@accelerator("Ctrl+O")
36 			void Open(FileName!() filename) {
37 				import std.file;
38 				textEdit.content = std.file.readText(filename);
39 			}
40 
41 			@icon(GenericIcons.Save)
42 			@toolbar("File")
43 			@accelerator("Ctrl+S")
44 			@hotkey('s')
45 			void Save() {
46 				// these are still functions, so of course you can
47 				// still call them yourself too
48 				Save_As(previousFileReferenced);
49 			}
50 
51 			// underscores translate to spaces in the visible name
52 			@hotkey('a')
53 			void Save_As(FileName!() filename) {
54 				import std.file;
55 				std.file.write(previousFileReferenced, textEdit.content);
56 			}
57 
58 			// you can put the annotations before or after the function name+args and it works the same way
59 			@separator
60 			void Exit() @accelerator("Alt+F4") @hotkey('x') {
61 				window.close();
62 			}
63 		}
64 
65 		@menu("&Edit") {
66 			// not putting accelerators here because the text edit widget
67 			// does it locally, so no need to duplicate it globally.
68 
69 			@icon(GenericIcons.Undo)
70 			void Undo() @toolbar("Undo") {
71 				textEdit.undo();
72 			}
73 
74 			@separator
75 
76 			@icon(GenericIcons.Cut)
77 			void Cut() @toolbar("Edit") {
78 				textEdit.cut();
79 			}
80 			@icon(GenericIcons.Copy)
81 			void Copy() @toolbar("Edit") {
82 				textEdit.copy();
83 			}
84 			@icon(GenericIcons.Paste)
85 			void Paste() @toolbar("Edit") {
86 				textEdit.paste();
87 			}
88 
89 			@separator
90 			void Select_All() {
91 				textEdit.selectAll();
92 			}
93 		}
94 
95 		@menu("Help") {
96 			void About() @accelerator("F1") {
97 				window.messageBox("A minigui sample program.");
98 			}
99 
100 			// @label changes the name in the menu from what is in the code
101 			@label("In Menu Name")
102 			void otherNameInCode() {}
103 		}
104 	}
105 
106 	// declare the object that holds the commands, and set
107 	// and members you want from it
108 	Commands commands;
109 
110 	// and now tell minigui to do its magic and create the ui for it!
111 	window.setMenuAndToolbarFromAnnotatedCode(commands);
112 
113 	// then, loop the window normally;
114 	window.loop();
115 
116 	// important to note that the `commands` variable must live through the window's whole life cycle,
117 	// or you can have crashes. If you declare the variable and loop in different functions, make sure
118 	// you do `new Commands` so the garbage collector can take over management of it for you.
119 }

Note that you can call this function multiple times and it will add the items in order to the given items.

  1. void setMenuAndToolbarFromAnnotatedCode(T t)
    class MainWindow
    void
    setMenuAndToolbarFromAnnotatedCode
    (
    T
    )
    (
    ref T t
    )
    if (
    !is(T == class) &&
    !is(T == interface)
    )
  2. void setMenuAndToolbarFromAnnotatedCode(T t)

Meta