tkD--来自TCL/TK之D语言跨平台GUI库

D越来越有玩头了~~

感觉一下代码的流畅:

  1 module main;
  2 
  3 /**
  4  * Imports.
  5  */
  6 import std.algorithm;
  7 import std.array;
  8 import std.datetime;
  9 import std.file;
 10 import tkd.tkdapplication;
 11 
 12 /**
 13  * Sample application.
 14  */
 15 class Application : TkdApplication
 16 {
 17     /**
 18      * Widgets we need access to on the class level.
 19      */
 20     private Entry _entry;
 21     private ProgressBar _progressBar;
 22     private Canvas _canvas;
 23     private Entry _fontEntry;
 24     private Entry _colorEntry;
 25     private Entry _directoryEntry;
 26     private Entry _openFileEntry;
 27     private Entry _saveFileEntry;
 28     private Entry _messageEntry;
 29 
 30     /**
 31      * Open the font dialog.
 32      *
 33      * Params:
 34      *     args = The callback args.
 35      */
 36     private void openFontDialog(CommandArgs args)
 37     {
 38         auto dialog = new FontDialog("Choose a font")
 39             .setCommand(delegate(CommandArgs args){
 40                 this._fontEntry.setValue(args.dialog.font);
 41             })
 42             .show();
 43     }
 44 
 45     /**
 46      * Open the color dialog.
 47      *
 48      * Params:
 49      *     args = The callback args.
 50      */
 51     private void openColorDialog(CommandArgs args)
 52     {
 53         auto dialog = new ColorDialog("Choose a color")
 54             .setInitialColor(Color.beige)
 55             .show();
 56         this._colorEntry.setValue(dialog.getResult());
 57     }
 58 
 59     /**
 60      * Open the directory dialog.
 61      *
 62      * Params:
 63      *     args = The callback args.
 64      */
 65     private void openDirectoryDialog(CommandArgs args)
 66     {
 67         auto dialog = new DirectoryDialog("Choose a directory")
 68             .setDirectoryMustExist(true)
 69             .show();
 70         this._directoryEntry.setValue(dialog.getResult());
 71     }
 72 
 73     /**
 74      * Open the open file dialog.
 75      *
 76      * Params:
 77      *     args = The callback args.
 78      */
 79     private void openOpenFileDialog(CommandArgs args)
 80     {
 81         auto dialog = new OpenFileDialog()
 82             .setMultiSelection(true)
 83             .setDefaultExtension(".dmo")
 84             .addFileType("{{All files} {*}}")
 85             .addFileType("{{D language files} {.d .di}}")
 86             .addFileType("{{HTML files} {.htm .html}}")
 87             .addFileType("{{Text files} {.txt}}")
 88             .setInitialDirectory("~")
 89             .setInitialFile("file-to-open.dmo")
 90             .show();
 91         this._openFileEntry.setValue(dialog.getResults().join(" "));
 92     }
 93 
 94     /**
 95      * Open the save file dialog.
 96      *
 97      * Params:
 98      *     args = The callback args.
 99      */
100     private void openSaveFileDialog(CommandArgs args)
101     {
102         auto dialog = new SaveFileDialog()
103             .setConfirmOverwrite(true)
104             .setDefaultExtension(".dmo")
105             .addFileType("{{All files} {*}}")
106             .addFileType("{{D language files} {.d .di}}")
107             .addFileType("{{HTML files} {.htm .html}}")
108             .addFileType("{{Text files} {.txt}}")
109             .setInitialDirectory("~")
110             .setInitialFile("file-to-save.dmo")
111             .show();
112         this._saveFileEntry.setValue(dialog.getResult());
113     }
114 
115     /**
116      * Open the message dialog.
117      *
118      * Params:
119      *     args = The callback args.
120      */
121     private void openMessageDialog(CommandArgs args)
122     {
123         auto dialog = new MessageDialog()
124             .setMessage("Lorem ipsum dolor sit amet.")
125             .setDetailMessage("Nunc at aliquam arcu. Sed eget tellus ligula.
Sed egestas est et tempus cursus.")
126             .setType(MessageDialogType.okcancel)
127             .show();
128         this._messageEntry.setValue(dialog.getResult());
129     }
130 
131     /**
132      * Mark a point in the canvas to drag from.
133      *
134      * Params:
135      *     args = The callback args.
136      */
137     private void mark(CommandArgs args)
138     {
139         this._canvas.setScanMark(args.event.x, args.event.y);
140     }
141 
142     /**
143      * Drag the canvas to reposition the contents.
144      *
145      * Params:
146      *     args = The callback args.
147      */
148     private void drag(CommandArgs args)
149     {
150         this._canvas.scanDragTo(args.event.x, args.event.y);
151     }
152 
153     /**
154      * Show the about box.
155      */
156     private void showAbout(CommandArgs args)
157     {
158         auto dialog = new MessageDialog("About")
159             .setMessage("Tkd Showcase")
160             .setDetailMessage("An showcase Tkd application demonstrating menus, widgets and dialogs.

The possiblities are endless.")
161             .show();
162     }
163 
164     /**
165      * Create the menu.
166      */
167     private void createMenu()
168     {
169         auto menuBar = new MenuBar(this.mainWindow);
170 
171         auto fileMenu = new Menu(menuBar, "File", 0)
172             .addEntry(new EmbeddedPng!("cancel.png"), "Quit", &this.exitApplication, ImagePosition.left, "Ctrl-Q");
173 
174         auto helpMenu = new Menu(menuBar, "Help", 0)
175             .addEntry(new EmbeddedPng!("help.png"), "About...", &this.showAbout, ImagePosition.left, "F1");
176     }
177 
178     /**
179      * Create the widget pane for the note book.
180      *
181      * Returns:
182      *     The widget pane.
183      */
184     private Frame createWidgetPane()
185     {
186         auto widgetPane = new Frame();
187 
188         auto entryLabelFrame = new LabelFrame(widgetPane, "Text Entry")
189             .pack(10, 0, GeometrySide.top, GeometryFill.both, AnchorPosition.center, true);
190             auto entry1 = new Text(entryLabelFrame)
191                 .setWidth(0)
192                 .setHeight(3)
193                 .appendText("Nullam sapien lectus, aliquet sit amet quam et, sagittis porttitor dolor.")
194                 .pack(5, 0, GeometrySide.bottom, GeometryFill.both, AnchorPosition.northWest, true);
195             this._entry = new Entry(entryLabelFrame)
196                 .pack(5, 0, GeometrySide.left, GeometryFill.x, AnchorPosition.northWest, true);
197             auto entry3 = new SpinBox(entryLabelFrame)
198                 .setData(["foo", "bar", "baz", "qux"])
199                 .setWrap(true)
200                 .setWidth(5)
201                 .pack(5, 0, GeometrySide.left);
202             auto entry4 = new ComboBox(entryLabelFrame)
203                 .setData(["Option 1", "Option 2", "Option 3"])
204                 .setValue("Option 1")
205                 .pack(5, 0, GeometrySide.left, GeometryFill.x, AnchorPosition.northWest, true);
206 
207         auto rangeLabelFrame = new LabelFrame(widgetPane, "Progress & Scale")
208             .pack(10, 0, GeometrySide.bottom, GeometryFill.both, AnchorPosition.center);
209             this._progressBar = new ProgressBar(rangeLabelFrame)
210                 .setMaxValue(10)
211                 .setValue(4)
212                 .pack(5, 0, GeometrySide.top, GeometryFill.x, AnchorPosition.center, true);
213             auto scale = new Scale(rangeLabelFrame)
214                 .setFromValue(10)
215                 .setToValue(0)
216                 .setCommand(delegate(CommandArgs args){
217                     auto scale = cast(Scale)args.element;
218                     this._progressBar.setValue(scale.getValue());
219                 })
220                 .setValue(4)
221                 .pack(5, 0, GeometrySide.top, GeometryFill.x, AnchorPosition.center, true);
222 
223         auto buttonLabelFrame = new LabelFrame(widgetPane, "Buttons")
224             .pack(10, 0, GeometrySide.left, GeometryFill.both, AnchorPosition.center, true);
225             auto button1 = new Button(buttonLabelFrame, "Text button")
226                 .pack(5);
227             auto button2 = new Button(buttonLabelFrame, new EmbeddedPng!("thumbnail.png"), "Image button", ImagePosition.left)
228                 .pack(5);
229             auto buttonMenu = new Menu()
230                 .addEntry("Option 1", delegate(CommandArgs args){})
231                 .addEntry("Option 2", delegate(CommandArgs args){})
232                 .addEntry("Option 3", delegate(CommandArgs args){});
233             auto button3 = new MenuButton(buttonLabelFrame, "Menu button", buttonMenu)
234                 .pack(5);
235 
236         auto checkBoxLabelFrame = new LabelFrame(widgetPane, "Check buttons")
237             .pack(10, 0, GeometrySide.left, GeometryFill.both, AnchorPosition.center, true);
238             auto checkButton1 = new CheckButton(checkBoxLabelFrame, "Option 1")
239                 .check()
240                 .pack(5);
241             auto checkButton2 = new CheckButton(checkBoxLabelFrame, "Option 2")
242                 .pack(5);
243             auto checkButton3 = new CheckButton(checkBoxLabelFrame, "Option 3")
244                 .pack(5);
245 
246         auto radioLabelFrame = new LabelFrame(widgetPane, "Radio buttons")
247             .pack(10, 0, GeometrySide.left, GeometryFill.both, AnchorPosition.center, true);
248             auto radioButton1 = new RadioButton(radioLabelFrame, "Option 1")
249                 .setSelectedValue("1")
250                 .select()
251                 .pack(5);
252             auto radioButton2 = new RadioButton(radioLabelFrame, "Option 2")
253                 .setSelectedValue("2")
254                 .pack(5);
255             auto radioButton3 = new RadioButton(radioLabelFrame, "Option 3")
256                 .setSelectedValue("3")
257                 .pack(5);
258 
259         return widgetPane;
260     }
261 
262     /**
263      * Create the paned pane for the note book.
264      *
265      * Returns:
266      *     The paned pane.
267      */
268     private Frame createPanedPane()
269     {
270         auto panedPane = new Frame();
271 
272             auto panedWindow = new PanedWindow(panedPane);
273 
274                 auto rows = new TreeViewRow(["Computer"], true, ["computer"]);
275                 rows.children ~= new TreeViewRow(["Documents"], true, ["folder"]);
276                     rows.children[0].children ~= new TreeViewRow(["Important notes.txt"], true, ["file"]);
277                     rows.children[0].children ~= new TreeViewRow(["The D Programming Language.pdf"], true, ["pdf"]);
278                 rows.children ~= new TreeViewRow(["Pictures"], true, ["folder"]);
279                     rows.children[1].children ~= new TreeViewRow(["Gary and Tessa.jpg"], true, ["image"]);
280                 rows.children ~= new TreeViewRow(["Videos"], true, ["folder"]);
281                     rows.children[2].children ~= new TreeViewRow(["Carlito's Way (1993).mpg"], true, ["video"]);
282                     rows.children[2].children ~= new TreeViewRow(["Aliens (1986).mpg"], true, ["video"]);
283 
284                 auto tree1 = new TreeView(panedWindow)
285                     .setHeading("Directory listing")
286                     .setTag("computer", new EmbeddedPng!("computer.png"))
287                     .setTag("folder", new EmbeddedPng!("folder.png"))
288                     .setTag("file", new EmbeddedPng!("page.png"))
289                     .setTag("pdf", new EmbeddedPng!("page_white_acrobat.png"))
290                     .setTag("video", new EmbeddedPng!("film.png"))
291                     .setTag("image", new EmbeddedPng!("images.png"))
292                     .addRow(rows);
293 
294                 auto tree2 = new TreeView(panedWindow)
295                     .setHeading("Film")
296                     .setWidth(250)
297                     .addColumn(new TreeViewColumn("Year").setWidth(20))
298                     .addColumn(new TreeViewColumn("IMDB ranking").setWidth(50))
299                     .addRow(new TreeViewRow(["The Shawshank Redemption", "1994", "1"]))
300                     .addRow(new TreeViewRow(["The Godfather", "1972", "2"]))
301                     .addRow(new TreeViewRow(["The Godfather: Part II", "1974", "3"]))
302                     .addRow(new TreeViewRow(["The Dark Knight", "2008", "4"]))
303                     .addRow(new TreeViewRow(["Pulp Fiction", "1994", "5"]))
304                     .addRow(new TreeViewRow(["The Good, the Bad and the Ugly", "1966", "6"]))
305                     .addRow(new TreeViewRow(["Schindler's List", "1993", "7"]))
306                     .addRow(new TreeViewRow(["Angry Men", "1957", "8"]))
307                     .addRow(new TreeViewRow(["The Lord of the Rings: The Return of the King", "2003", "9"]))
308                     .addRow(new TreeViewRow(["Fight Club", "1999", "10"]));
309 
310         panedWindow
311             .addPane(tree1).setPaneWeight(0, 1)
312             .addPane(tree2).setPaneWeight(1, 1)
313             .pack(10, 0, GeometrySide.top, GeometryFill.both, AnchorPosition.center, true);
314 
315         return panedPane;
316     }
317 
318     /**
319      * Create the canvas pane for the note book.
320      *
321      * Returns:
322      *     The canvas pane.
323      */
324     private Frame createCanvasPane()
325     {
326         auto canvasPane = new Frame();
327 
328             auto container = new Frame(canvasPane)
329                 .pack(10, 0, GeometrySide.top, GeometryFill.both, AnchorPosition.center, true);
330 
331             container.configureGeometryColumn(0, 1);
332             container.configureGeometryRow(0, 1);
333 
334                 this._canvas = new Canvas(container, Color.bisque)
335                     .setCursor(Cursor.hand1)
336                     .setScrollRegion(-300, -250, 610, 500)
337                     .addItem(new CanvasRectangle([10, 10, 200, 100]).addTag("tagged"))
338                     .addItem(new CanvasArc([10, 110, 110, 210], CanvasArcStyle.pie, Color.paleGreen))
339                     .addItem(new CanvasImage([210, 10], new EmbeddedPng!("thumbnail.png")))
340                     .addItem(new CanvasImage([260, 10], new EmbeddedGif!("thumbnail.gif")))
341                     .addItem(new CanvasLine([120, 110, 200, 110, 200, 160]).setArrowPosition(CanvasLineArrow.last))
342                     .addItem(new CanvasOval([10, 170, 200, 245], Color.rosyBrown3))
343                     .addItem(new CanvasPolygon([220, 80, 320, 80, 300, 120, 240, 120], Color.mediumPurple))
344                     .addItem(new CanvasText([30, 192], "Tkd Canvas", Color.white).setFont("{Times New Roman} 22 bold"))
345                     .addItem(new CanvasWidget([220, 140], new Button("Embedded
Widget", new EmbeddedPng!("error.png"))).setWidth(100).setHeight(100))
346                     .addTagConfig(new CanvasTagConfig("tagged").setFillColor(Color.salmon))
347                     .setXView(0.25)
348                     .setYView(0.24)
349                     .bind("<ButtonPress-1>", &this.mark)
350                     .bind("<B1-Motion>", &this.drag);
351 
352                 auto xscroll = new XScrollBar(container)
353                     .attachWidget(this._canvas)
354                     .grid(0, 1, 0, 0, 1, 1, "esw");
355 
356                 auto yscroll = new YScrollBar(container)
357                     .attachWidget(this._canvas)
358                     .grid(1, 0, 0, 0, 1, 1, "nes");
359 
360                 this._canvas
361                     .attachXScrollBar(xscroll)
362                     .attachYScrollBar(yscroll)
363                     .grid(0, 0, 0, 0, 1, 1, "nesw");
364 
365         return canvasPane;
366     }
367 
368     /**
369      * Create the dialog pane for the note book.
370      *
371      * Returns:
372      *     The dialog pane.
373      */
374     private Frame createDialogPane()
375     {
376         auto dialogPane = new Frame();
377 
378             auto modalLabelFrame = new LabelFrame(dialogPane, "Modal")
379                 .configureGeometryColumn(1, 1)
380                 .pack(10, 0, GeometrySide.top, GeometryFill.both, AnchorPosition.center, true);
381 
382                 auto colorButton = new Button(modalLabelFrame, new EmbeddedPng!("color_swatch.png"), "Color", ImagePosition.left)
383                     .setCommand(&this.openColorDialog)
384                     .grid(0, 0, 10);
385 
386                 this._colorEntry = new Entry(modalLabelFrame)
387                     .grid(1, 0, 10, 0, 1, 1, "ew");
388 
389                 auto directoryButton = new Button(modalLabelFrame, new EmbeddedPng!("chart_organisation.png"), "Directory", ImagePosition.left)
390                     .setCommand(&this.openDirectoryDialog)
391                     .grid(0, 1, 10);
392 
393                 this._directoryEntry = new Entry(modalLabelFrame)
394                     .setWidth(40)
395                     .grid(1, 1, 10, 0, 1, 1, "ew");
396 
397                 auto fileOpenButton = new Button(modalLabelFrame, new EmbeddedPng!("folder_page.png"), "Open File", ImagePosition.left)
398                     .setCommand(&this.openOpenFileDialog)
399                     .grid(0, 2, 10);
400 
401                 this._openFileEntry = new Entry(modalLabelFrame)
402                     .setWidth(40)
403                     .grid(1, 2, 10, 0, 1, 1, "ew");
404 
405                 auto fileSaveButton = new Button(modalLabelFrame, new EmbeddedPng!("disk.png"), "Save File", ImagePosition.left)
406                     .setCommand(&this.openSaveFileDialog)
407                     .grid(0, 3, 10);
408 
409                 this._saveFileEntry = new Entry(modalLabelFrame)
410                     .setWidth(40)
411                     .grid(1, 3, 10, 0, 1, 1, "ew");
412 
413                 auto messageButton = new Button(modalLabelFrame, new EmbeddedPng!("comment.png"), "Message", ImagePosition.left)
414                     .setCommand(&this.openMessageDialog)
415                     .grid(0, 4, 10);
416 
417                 this._messageEntry = new Entry(modalLabelFrame)
418                     .setWidth(40)
419                     .grid(1, 4, 10, 0, 1, 1, "ew");
420 
421             auto nonModalLabelFrame = new LabelFrame(dialogPane, "Non Modal")
422                 .configureGeometryColumn(1, 1)
423                 .pack(10, 0, GeometrySide.top, GeometryFill.both, AnchorPosition.center, true);
424 
425                 auto fontButton = new Button(nonModalLabelFrame, new EmbeddedPng!("style.png"), "Font", ImagePosition.left)
426                     .setCommand(&this.openFontDialog)
427                     .grid(0, 0, 10);
428 
429                 this._fontEntry = new Entry(nonModalLabelFrame)
430                     .setWidth(40)
431                     .grid(1, 0, 10, 0, 1, 1, "ew");
432 
433         return dialogPane;
434     }
435 
436     /**
437      * Set up the key bindings for the application.
438      */
439     private void setUpKeyBindings()
440     {
441         this.mainWindow.bind("<F1>", &this.showAbout);
442         this.mainWindow.bind("<Control-q>", &this.exitApplication);
443     }
444 
445     /**
446      * Initialise the user interface.
447      */
448     override protected void initInterface()
449     {
450         this.mainWindow.setTitle("Tkd Showcase");
451         this.mainWindow.setMinSize(550, 560);
452         this.mainWindow.setDefaultIcon([new EmbeddedPng!("tkicon.png")]);
453 
454         this.mainWindow.setProtocolCommand(WindowProtocol.deleteWindow, delegate(CommandArgs args){
455             this.showAbout(args);
456             this.exitApplication(args);
457         });
458 
459         this.mainWindow.setIdleCommand(delegate(CommandArgs args){
460             this._entry.setValue(Clock.currTime().toLocalTime().toSimpleString().findSplitBefore(".")[0]);
461             this.mainWindow.setIdleCommand(args.callback, 1000);
462         });
463 
464         this.createMenu();
465 
466         auto noteBook   = new NoteBook();
467         auto widgetPane = this.createWidgetPane();
468         auto panedPane  = this.createPanedPane();
469         auto canvasPane = this.createCanvasPane();
470         auto dialogPane = this.createDialogPane();
471 
472         noteBook
473             .addTab("Widgets", widgetPane).setTabImage(0, new EmbeddedPng!("layout_content.png"), ImagePosition.left)
474             .addTab("Panes", panedPane).setTabImage(1, new EmbeddedPng!("application_tile_horizontal.png"), ImagePosition.left)
475             .addTab("Canvas", canvasPane).setTabImage(2, new EmbeddedPng!("shape_ungroup.png"), ImagePosition.left)
476             .addTab("Dialogs", dialogPane).setTabImage(3, new EmbeddedPng!("application_double.png"), ImagePosition.left)
477             .pack(10, 0, GeometrySide.top, GeometryFill.both, AnchorPosition.center, true);
478 
479         auto exitButton = new Button("Exit")
480             .setCommand(&this.exitApplication)
481             .pack(5);
482 
483         auto sizeGrip = new SizeGrip(this.mainWindow)
484             .pack(0, 0, GeometrySide.bottom, GeometryFill.none, AnchorPosition.southEast);
485 
486         this.setUpKeyBindings();
487     }
488 
489     /**
490      * Exit the application.
491      *
492      * Params:
493      *     args = The command arguments.
494      */
495     private void exitApplication(CommandArgs args)
496     {
497         this.exit();
498     }
499 
500 }
501 
502 /**
503  * Main entry point.
504  *
505  * Params:
506  *     args = An array of command line arguments passed to this program.
507  */
508 void main(string[] args)
509 {
510     auto app = new Application();
511     app.run();
512 }

原文地址:https://www.cnblogs.com/godspeedsam/p/3836195.html