-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathfeed.xml
2675 lines (1979 loc) · 181 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="http://localhost:4000/feed.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/" rel="alternate" type="text/html" /><updated>2024-12-09T07:09:41-05:00</updated><id>http://localhost:4000/feed.xml</id><title type="html">gtkDcoding</title><subtitle>Simple examples of how to use GtkD to build GUI applications.</subtitle><author><name>Ron Tarrant</name></author><entry><title type="html">0115: GTK GIO Application Flags - Opening Files</title><link href="http://localhost:4000/posts/0115-gtk-gio-app-open-flag.html" rel="alternate" type="text/html" title="0115: GTK GIO Application Flags - Opening Files" /><published>2021-09-24T00:00:00-04:00</published><updated>2021-09-24T00:00:00-04:00</updated><id>http://localhost:4000/posts/0115-gtk-gio-app-open-flag</id><content type="html" xml:base="http://localhost:4000/posts/0115-gtk-gio-app-open-flag.html"><![CDATA[<h1 id="0115--gtkgio-open-flag">0115 – GTK/GIO Open Flag</h1>
<p>The next <code class="language-plaintext highlighter-rouge">ApplicationFlag</code>, <code class="language-plaintext highlighter-rouge">HANDLES_OPEN</code>, gives us a mechanism for opening files from the command line. Such things are relatively straightforward anyway, but perhaps we’ll find an advantage or two by using what <em>GIO</em> has to offer. Let’s dig in and find out, shall we?</p>
<p>We’ll do this in two steps. Firstly, we’ll look at the basics—grabbing the file names from the command line—and secondly, we’ll add just enough code to open each file in its own window.</p>
<h2 id="importing-the-gio-file-abstraction">Importing the GIO File Abstraction</h2>
<!-- 0, 1 -->
<!-- first occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
<div class="frame-header">
Results of this example:
</div>
<div class="frame-screenshot">
<figure>
<img id="img0" src="/images/screenshots/020_app/app_05_open_flag.png" alt="Current example output" /> <!-- img# -->
<!-- Modal for screenshot -->
<div id="modal0" class="modal"> <!-- modal# -->
<span class="close0">×</span> <!-- close# -->
<img class="modal-content" id="img00" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal0"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img0"); // img#
var modalImg = document.getElementById("img00"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close0")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Demonstration where multiple file names are given on the command line.
</figcaption>
</figure>
</div>
<div class="frame-terminal">
<figure class="right">
<img id="img1" src="/images/screenshots/020_app/app_05_open_flag_term.png" alt="Current example terminal output" /> <!-- img#, filename -->
<!-- Modal for terminal shot -->
<div id="modal1" class="modal"> <!-- modal# -->
<span class="close1">×</span> <!-- close# -->
<img class="modal-content" id="img11" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal1"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img1"); // img#
var modalImg = document.getElementById("img11"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close1")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Top: no file names given on the command line. Bottom: two file names given.
</figcaption>
</figure>
</div>
<div class="frame-footer"> <!-- ------------- filename (below) --------- -->
The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/020_app/app_05_open_flag.d" target="_blank">here</a>.
</div>
</div>
<!-- end of snippet for first (1st) occurrence of application and terminal screen shots on a single page -->
<p>The <em>GIO</em> construct that helps us handle files is called <code class="language-plaintext highlighter-rouge">gio.FileIF</code>. It’s not really an interface, but a sort-of wrapper standing in for a <em>C</em>-language abstraction—<code class="language-plaintext highlighter-rouge">GFile</code>—which represents the vital statistics of a file. For our purposes, we don’t need to know a lot about this to use it, so we’ll skip the details. For now, just know we need this import statement to make this stuff work:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="n">gio</span><span class="p">.</span><span class="n">FileIF</span><span class="p">;</span>
</code></pre></div></div>
<h2 id="myapplication-changes">MyApplication Changes</h2>
<h3 id="raise-the-flag">Raise the Flag</h3>
<p>As we’ve done before, we declare the appropriate flag in the <code class="language-plaintext highlighter-rouge">MyApplication</code> class. And while we’re at it, let’s change the application <code class="language-plaintext highlighter-rouge">id</code> as well so it matches our current example:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ApplicationFlags</span> <span class="n">flags</span> <span class="p">=</span> <span class="n">ApplicationFlags</span><span class="p">.</span><span class="n">HANDLES_OPEN</span><span class="p">;</span>
<span class="nb">string</span> <span class="n">id</span> <span class="p">=</span> <span class="s">"com.gtkdcoding.app.app_05_open_flag"</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="hook-up-the-callback">Hook up the Callback</h3>
<p>The initializer method needs a little something, too:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">addOnOpen</span><span class="p">(&</span><span class="n">onOpen</span><span class="p">);</span>
</code></pre></div></div>
<p>Basically, just hook up the signal. Note that we don’t need the <code class="language-plaintext highlighter-rouge">HANDLES_COMMAND_LINE</code> flag to make this work, even though that might seem like the case (it did to me at first).</p>
<h3 id="messing-with-the-activate-method">Messing with the activate() Method</h3>
<p>This is a pretty small change from our last demo. There, we passed in an array containing the dimensions of the window we were about to open. This time, we forego that in favour of passing in whatever arguments the user types on the command line. For purposes of demonstration, we hope these arguments will be valid file names so we don’t have to write <code class="language-plaintext highlighter-rouge">try</code>/<code class="language-plaintext highlighter-rouge">catch</code> statements. But feel free to add those if you want.</p>
<p>Anyway, <code class="language-plaintext highlighter-rouge">activate()</code> now looks like this:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">activate</span><span class="p">(</span><span class="nb">string</span> <span class="n">filename</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"activate called"</span><span class="p">);</span>
<span class="n">AppWindow</span> <span class="n">appWindow</span> <span class="p">=</span> <span class="k">new</span> <span class="n">AppWindow</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="n">filename</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// activate()</span>
</code></pre></div></div>
<p>We’ve dispensed with the <code class="language-plaintext highlighter-rouge">dimensions</code> argument—an array of integers—and replaced it with <code class="language-plaintext highlighter-rouge">filename</code>—a string—which is the name of the file we’ll be opening in a window instance.</p>
<p>This method is called once for each file name provided on the command line.</p>
<h3 id="changes-to-the-onactivate-method">Changes to the onActivate() Method</h3>
<p>Here’s another small change:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">onActivate</span><span class="p">(</span><span class="n">GioApplication</span> <span class="n">app</span><span class="p">)</span> <span class="c1">// non-advanced syntax</span>
<span class="p">{</span>
<span class="n">AppWindow</span> <span class="n">appWindow</span> <span class="p">=</span> <span class="k">new</span> <span class="n">AppWindow</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="kc">null</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"triggered onActivate..."</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"\tApplication ID: "</span><span class="p">,</span> <span class="n">getApplicationId</span><span class="p">());</span>
<span class="p">}</span> <span class="c1">// onActivate()</span>
</code></pre></div></div>
<p>The reason we have another instantiation of <code class="language-plaintext highlighter-rouge">AppWindow</code> here is to deal with the possibility that the user gives no arguments. Note that—depending on circumstances—either <code class="language-plaintext highlighter-rouge">activate()</code> or <code class="language-plaintext highlighter-rouge">onActivate()</code> is called, but not both. Here’s the low-down:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">activate()</code> is called once for each file name passed in, whether those file names are valid or not, and</li>
<li><code class="language-plaintext highlighter-rouge">onActivate()</code> is called if no arguments whatsoever are given.</li>
</ul>
<p><em>Note: If multiple non-valid file names are given, <code class="language-plaintext highlighter-rouge">activate()</code> is still called multiple times and multiple windows are opened. A little error checking will not go amiss here, but I’ll leave that to your imagination and skill.</em></p>
<h3 id="a-new-callback--onopen">A New Callback – onOpen()</h3>
<p>It’s relatively trivial, so here’s the entire method:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">onOpen</span><span class="p">(</span><span class="n">FileIF</span><span class="p">[]</span> <span class="n">files</span><span class="p">,</span> <span class="nb">string</span> <span class="n">hint</span><span class="p">,</span> <span class="n">GioApplication</span> <span class="n">app</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"triggered onOpen..."</span><span class="p">);</span>
<span class="k">foreach</span><span class="p">(</span><span class="n">file</span><span class="p">;</span> <span class="n">files</span><span class="p">)</span>
<span class="p">{</span>
<span class="nb">string</span> <span class="n">name</span> <span class="p">=</span> <span class="n">file</span><span class="p">.</span><span class="n">getPath</span><span class="p">();</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"file name: "</span><span class="p">,</span> <span class="n">name</span><span class="p">);</span>
<span class="n">activate</span><span class="p">(</span><span class="n">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="c1">// onOpen()</span>
</code></pre></div></div>
<p>This simple method steps through an array of <code class="language-plaintext highlighter-rouge">FileIF</code> objects, grabs the full path of each, then calls <code class="language-plaintext highlighter-rouge">activate()</code> for each one… as mentioned above.</p>
<p>The second argument—<code class="language-plaintext highlighter-rouge">string hint</code>—allows for different modes when opening a file (edit, view, etc.) and it’s suggested that unless we have a specific need for this type of thing, we should just leave it be. So we will.</p>
<p>Let’s move on to the next step where we actually load files into these windows…</p>
<h2 id="loading-text-files">Loading Text Files</h2>
<!-- 2, 3 -->
<!-- second occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
<div class="frame-header">
Results of this example:
</div>
<div class="frame-screenshot">
<figure>
<img id="img2" src="/images/screenshots/020_app/app_06_open_and_load.png" alt="Current example output" /> <!-- img# -->
<!-- Modal for screenshot -->
<div id="modal2" class="modal"> <!-- modal# -->
<span class="close2">×</span> <!-- close# -->
<img class="modal-content" id="img22" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal2"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img2"); // img#
var modalImg = document.getElementById("img22"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close2")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Two file names given on the command line.
</figcaption>
</figure>
</div>
<div class="frame-terminal">
<figure class="right">
<img id="img3" src="/images/screenshots/020_app/app_06_open_and_load_term.png" alt="Current example terminal output" /> <!-- img#, filename -->
<!-- Modal for terminal shot -->
<div id="modal3" class="modal"> <!-- modal# -->
<span class="close3">×</span> <!-- close# -->
<img class="modal-content" id="img33" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal3"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img3"); // img#
var modalImg = document.getElementById("img33"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close3")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Two file names given on the command line. (click for enlarged view)
</figcaption>
</figure>
</div>
<div class="frame-footer"> <!--------- filename (below) ------------>
The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/020_app/app_06_open_and_load.d" target="_blank">here</a>.
</div>
</div>
<!-- end of snippet for second (2nd) occurrence of application and terminal screen shots on a single page -->
<p>We’ve seen the <em>GTK</em> code to accomplish this before—the bits and bobs that slap a <code class="language-plaintext highlighter-rouge">TextView</code> into a <code class="language-plaintext highlighter-rouge">Window</code>—so that part, I’ll skip. If you want a refresher, take a quick look at <a href="https:/.com/posts/0069-textview-and-textbuffer.html">blog post #0069</a>.</p>
<p>The one thing we haven’t covered is the <em>D</em> code that opens and reads the file. Here’s what that looks like:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">file</span> <span class="p">=</span> <span class="n">File</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">"r"</span><span class="p">);</span>
<span class="k">while</span> <span class="p">(!</span><span class="n">file</span><span class="p">.</span><span class="n">eof</span><span class="p">())</span>
<span class="p">{</span>
<span class="nb">string</span> <span class="n">line</span> <span class="p">=</span> <span class="n">file</span><span class="p">.</span><span class="n">readln</span><span class="p">();</span>
<span class="n">content</span> <span class="p">~=</span> <span class="n">line</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">textBuffer</span><span class="p">.</span><span class="n">setText</span><span class="p">(</span><span class="n">content</span><span class="p">);</span>
<span class="n">file</span><span class="p">.</span><span class="n">close</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Pretty straightforward. We start by making sure the <code class="language-plaintext highlighter-rouge">filename</code> variable contains a string, then dip into <em>D</em>’s <code class="language-plaintext highlighter-rouge">stdio</code> library to open the file in read mode.</p>
<p>The <code class="language-plaintext highlighter-rouge">while</code> loop reads the file one line at a time and concatenates it to the <code class="language-plaintext highlighter-rouge">content</code> variable.</p>
<p>Once that’s done, <code class="language-plaintext highlighter-rouge">content</code> is dumped into the <code class="language-plaintext highlighter-rouge">TextBuffer</code> and we close the file.</p>
<h2 id="conclusion">Conclusion</h2>
<p>So, now we’ve read file names from the command line and opened them, each in their own window. Next time, we’ll look at command line switches.</p>
<p>‘Til then, let’s all do our best to stay sane. These trying times are a challenge—like setting out to design a garbage collector on your first day with a new language while simultaneously trying to work out the plot of <em>Lost</em>—but we can survive and flourish if we all keep our heads… and our distance.</p>
<p>Be safe.</p>
<div class="blog-nav">
<div style="float: left;">
<a href="/posts/0114-gtk-gio-app-flags-and-cl-args.html">Previous: GTK GIO - Command Line Arguments</a>
</div>
<!-- <div style="float: right;">
<a href="/posts/0116-gtk-gio-app-cl-switches.html">Next: GTK/GIO - Command Line Switches</a>
</div> -->
</div>]]></content><author><name>Ron Tarrant</name></author><category term="app" /><summary type="html"><![CDATA[How GTK/GIO flags that allow opening files from the command line.]]></summary></entry><entry><title type="html">0114: GTK GIO Application Flags and Command Line Arguments</title><link href="http://localhost:4000/posts/0114-gtk-gio-app-flags-and-cl-args.html" rel="alternate" type="text/html" title="0114: GTK GIO Application Flags and Command Line Arguments" /><published>2021-09-17T00:00:00-04:00</published><updated>2021-09-17T00:00:00-04:00</updated><id>http://localhost:4000/posts/0114-gtk-gio-app-flags-and-cl-args</id><content type="html" xml:base="http://localhost:4000/posts/0114-gtk-gio-app-flags-and-cl-args.html"><![CDATA[<h1 id="0114-gtkgio-application-flags-and-command-line-arguments">0114: GTK/GIO Application Flags and Command Line Arguments</h1>
<p>Today we’ll dig into passing command line arguments to a <em>GTK</em>/<em>GIO</em> application and start looking at the built-in mechanism that handles them.</p>
<h2 id="the-arguments">The Arguments</h2>
<!-- 0, 1 -->
<!-- first occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
<div class="frame-header">
Results of this example:
</div>
<div class="frame-screenshot">
<figure>
<img id="img0" src="/images/screenshots/020_app/app_04_commandline_arguments.png" alt="Current example output" /> <!-- img# -->
<!-- Modal for screenshot -->
<div id="modal0" class="modal"> <!-- modal# -->
<span class="close0">×</span> <!-- close# -->
<img class="modal-content" id="img00" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal0"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img0"); // img#
var modalImg = document.getElementById("img00"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close0")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Current example output
</figcaption>
</figure>
</div>
<div class="frame-terminal">
<figure class="right">
<img id="img1" src="/images/screenshots/020_app/app_04_commandline_arguments_term.png" alt="Current example terminal output" /> <!-- img#, filename -->
<!-- Modal for terminal shot -->
<div id="modal1" class="modal"> <!-- modal# -->
<span class="close1">×</span> <!-- close# -->
<img class="modal-content" id="img11" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal1"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img1"); // img#
var modalImg = document.getElementById("img11"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close1")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Current example terminal output (click for enlarged view)
</figcaption>
</figure>
</div>
<div class="frame-footer"> <!-- ------------- filename (below) --------- -->
The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/020_app/app_04_commandline_arguments.d" target="_blank">here</a>.
</div>
</div>
<!-- end of snippet for first (1st) occurrence of application and terminal screen shots on a single page -->
<p>As mentioned last time, command-line arguments are passed along to the <em>GIO</em> <code class="language-plaintext highlighter-rouge">Application</code>—a class object rather than the <code class="language-plaintext highlighter-rouge">Main</code> C-style struct we’ve used all along—and packed into an array. The flow of these arguments is:</p>
<ul>
<li>the user types the arguments,</li>
<li>the class initializer method then:
<ul>
<li>pulls them in — <code class="language-plaintext highlighter-rouge">this(string[] args)</code>,</li>
<li>passes them to the <code class="language-plaintext highlighter-rouge">GtkApplication.run()</code> method — <code class="language-plaintext highlighter-rouge">run(args)</code>, and</li>
</ul>
</li>
<li>they’re stored in an <code class="language-plaintext highlighter-rouge">ApplicationCommandLine</code> object.</li>
</ul>
<p>From there, we pull them out in our <code class="language-plaintext highlighter-rouge">onCommandLine()</code> method (which we’ll look at momentarily).</p>
<p>Now let’s take a gander at the initialization method in full:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">this</span><span class="p">(</span><span class="nb">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">super</span><span class="p">(</span><span class="n">id</span><span class="p">,</span> <span class="n">flags</span><span class="p">);</span>
<span class="n">addOnActivate</span><span class="p">(&</span><span class="n">onActivate</span><span class="p">);</span>
<span class="n">addOnCommandLine</span><span class="p">(&</span><span class="n">onCommandLine</span><span class="p">);</span>
<span class="n">addOnStartup</span><span class="p">(&</span><span class="n">onStartup</span><span class="p">);</span>
<span class="n">addOnShutdown</span><span class="p">(&</span><span class="n">onShutdown</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"registration before: "</span><span class="p">,</span> <span class="n">registration</span><span class="p">);</span>
<span class="n">registration</span> <span class="p">=</span> <span class="n">register</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"registration after: "</span><span class="p">,</span> <span class="n">registration</span><span class="p">);</span>
<span class="n">run</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// this()</span>
</code></pre></div></div>
<p>Notice that we’re using a signal to hook up command-line processing to a method just as we do with application activation, application start-up, or—for that matter—connecting any widget to an action.</p>
<p>Now, before we dig in further, I want to point out one other thing we need to take care of when deriving our <code class="language-plaintext highlighter-rouge">MyApplication</code> class from <code class="language-plaintext highlighter-rouge">GtkApplication</code>…</p>
<p>We need to tell <em>GTK</em>/<em>GIO</em> that we’re intending to handle command-line arguments and to do this, we declare a class attribute in the preamble:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ApplicationFlags</span> <span class="n">flags</span> <span class="p">=</span> <span class="n">ApplicationFlags</span><span class="p">.</span><span class="n">HANDLES_COMMAND_LINE</span><span class="p">;</span>
</code></pre></div></div>
<p>It’s an extra step compared to doing things the way we’re used to.</p>
<h3 id="parsing-parsing-over-the-bounding-command-line">Parsing, Parsing, Over the Bounding Command-line</h3>
<p>Now that <em>GIO</em> has done its part, it’s up to us to pick up the command-line argument baton and finish the race. How? We write a command-line parser. It’ll be written as a method similar to the widget action methods we’ve looked at so often in this blog. In this case, it takes this form:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="n">onCommandLine</span><span class="p">(</span><span class="n">ApplicationCommandLine</span> <span class="n">acl</span><span class="p">,</span> <span class="n">GioApplication</span> <span class="n">app</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">exitStatus</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nb">string</span><span class="p">[]</span> <span class="n">args</span> <span class="p">=</span> <span class="n">acl</span><span class="p">.</span><span class="n">getArguments</span><span class="p">();</span>
<span class="kt">int</span><span class="p">[]</span> <span class="n">dimensions</span> <span class="p">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">];</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"triggered onCommandLine..."</span><span class="p">);</span>
<span class="c1">// remove the application name from the string of args</span>
<span class="n">args</span> <span class="p">=</span> <span class="n">args</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"\tcommandline args: "</span><span class="p">,</span> <span class="n">args</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"\targs.length: "</span><span class="p">,</span> <span class="n">args</span><span class="p">.</span><span class="n">length</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">args</span><span class="p">.</span><span class="n">length</span> <span class="p">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"\tno args"</span><span class="p">);</span>
<span class="n">activate</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="p">;</span> <span class="n">i</span> <span class="p"><</span> <span class="n">args</span><span class="p">.</span><span class="n">length</span><span class="p">;</span> <span class="n">i</span> <span class="p">+=</span> <span class="mi">2</span><span class="p">)</span>
<span class="p">{</span>
<span class="nb">string</span> <span class="n">arg</span> <span class="p">=</span> <span class="n">args</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="k">switch</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">case</span> <span class="s">"width"</span><span class="p">:</span>
<span class="n">dimensions</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">=</span> <span class="n">to</span><span class="p">!</span><span class="kt">int</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="n">i</span> <span class="p">+</span> <span class="mi">1</span><span class="p">]);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="s">"height"</span><span class="p">:</span>
<span class="n">dimensions</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">=</span> <span class="n">to</span><span class="p">!</span><span class="kt">int</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="n">i</span> <span class="p">+</span> <span class="mi">1</span><span class="p">]);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">default</span><span class="p">:</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"arg: "</span><span class="p">,</span> <span class="n">arg</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"arg: "</span><span class="p">,</span> <span class="n">to</span><span class="p">!</span><span class="nb">string</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="n">i</span> <span class="p">+</span> <span class="mi">1</span><span class="p">]));</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">activate</span><span class="p">(</span><span class="n">dimensions</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">(</span><span class="n">exitStatus</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// onCommandLine()</span>
</code></pre></div></div>
<p>Note the method arguments:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">ApplicationCommandLine acl</code>, and</li>
<li><code class="language-plaintext highlighter-rouge">GioApplication app</code>.</li>
</ul>
<p>Earlier, we talked about the path our arguments take when they’re passed in. I didn’t mention their final destination which is—they get shoved into the <code class="language-plaintext highlighter-rouge">ApplicationCommandLine</code> class which is specifically designed for that purpose. Here in the parser method is where we retrieve them and get down to business.</p>
<p>In short (skipping down to the <code class="language-plaintext highlighter-rouge">if</code>/<code class="language-plaintext highlighter-rouge">else</code>), what we do here is:</p>
<ul>
<li>get rid of the application name (which, you’ll remember, is always retrieved along with the arguments) by <code class="language-plaintext highlighter-rouge">remove()</code>ing the zeroth element of the <code class="language-plaintext highlighter-rouge">args</code> array,</li>
<li>step through the remaining args two at a time,</li>
<li>check each against a pre-determined set of args we’re expecting (<code class="language-plaintext highlighter-rouge">“width”</code> and <code class="language-plaintext highlighter-rouge">“height”</code> in this case),</li>
<li>do a look-ahead to the next argument to get a value, and</li>
<li>calling the <code class="language-plaintext highlighter-rouge">activate()</code> method, passing in the width and height we’ve captured from the command line.</li>
</ul>
<h2 id="the-activate-method">The activate() Method</h2>
<p><em>GIO</em> has a default <code class="language-plaintext highlighter-rouge">activate()</code> method which gets called unless we override it. Here, that’s exactly what we’re doing.</p>
<p>If you run this demo without appending command line arguments, you’ll get a few bits of info dumped to the terminal, but that’s it. The demo exits. But adding even one command line argument changes that. A window opens… and if you don’t specify a <code class="language-plaintext highlighter-rouge">width</code> and <code class="language-plaintext highlighter-rouge">height</code>, each followed by a number, the window has a default size, the dimensions of which are object attributes in the preamble to the <code class="language-plaintext highlighter-rouge">AppWindow</code> class.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Because of space constraints, I’ve skimmed over a few things, so if you have questions, please ask them in the comments below.</p>
<p>Next time, we’ll carry on in this same vein, but turn to the <code class="language-plaintext highlighter-rouge">HANDLES_OPEN</code> flag to see how a list of files can be opened using these methods.</p>
<p>Until then, just remember Howard’s immortal words: “There’s no place for truth on the Internet.”</p>
<div class="blog-nav">
<div style="float: left;">
<a href="/posts/0113-gtk-gio-application-ids-signals.html">Previous: GTK GIO Applications - IDs and Signals</a>
</div>
<div style="float: right;">
<a href="/posts/0115-gtk-gio-app-open-flag.html">Next: GTK/GIO IV - Opening Files</a>
</div>
</div>]]></content><author><name>Ron Tarrant</name></author><category term="app" /><summary type="html"><![CDATA[How GTK/GIO uses flags in the processing command line arguments.]]></summary></entry><entry><title type="html">0113: GTK GIO Application IDs and Signals</title><link href="http://localhost:4000/posts/0113-gtk-gio-application-ids-signals.html" rel="alternate" type="text/html" title="0113: GTK GIO Application IDs and Signals" /><published>2021-09-10T00:00:00-04:00</published><updated>2021-09-10T00:00:00-04:00</updated><id>http://localhost:4000/posts/0113-gtk-gio-application-ids-signals</id><content type="html" xml:base="http://localhost:4000/posts/0113-gtk-gio-application-ids-signals.html"><![CDATA[<h1 id="0113-application-ids-and-signals">0113: Application IDs and Signals</h1>
<p>Continuing from last time when we started looking at GTK/GIO Applications, today let’s look at…</p>
<h2 id="application-ids">Application IDs</h2>
<!-- 0, 1 -->
<!-- first occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
<div class="frame-header">
Results of this example:
</div>
<div class="frame-screenshot">
<figure>
<img id="img0" src="/images/screenshots/020_app/app_02_barebones_with_id.png" alt="Current example output" /> <!-- img# -->
<!-- Modal for screenshot -->
<div id="modal0" class="modal"> <!-- modal# -->
<span class="close0">×</span> <!-- close# -->
<img class="modal-content" id="img00" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal0"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img0"); // img#
var modalImg = document.getElementById("img00"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close0")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Current example output
</figcaption>
</figure>
</div>
<div class="frame-terminal">
<figure class="right">
<img id="img1" src="/images/screenshots/020_app/app_02_barebones_with_id_term.png" alt="Current example terminal output" /> <!-- img#, filename -->
<!-- Modal for terminal shot -->
<div id="modal1" class="modal"> <!-- modal# -->
<span class="close1">×</span> <!-- close# -->
<img class="modal-content" id="img11" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal1"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img1"); // img#
var modalImg = document.getElementById("img11"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close1")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Current example terminal output (click for enlarged view)
</figcaption>
</figure>
</div>
<div class="frame-footer"> <!-- ------------- filename (below) --------- -->
The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/020_app/app_02_barebones_with_id.d" target="_blank">here</a>.
</div>
</div>
<!-- end of snippet for first (1st) occurrence of application and terminal screen shots on a single page -->
<p>Every <code class="language-plaintext highlighter-rouge">Application</code> has to have an <code class="language-plaintext highlighter-rouge">ID</code>, even if—as in our example from last time—it’s <code class="language-plaintext highlighter-rouge">null</code>. The intention is that each <code class="language-plaintext highlighter-rouge">Application</code> can be singled out for inter-process communication, even across the vastness of the Internet. This may seem like overkill, but if you think about it, how else can we guarantee finding a single remote application among the (possibly) millions that may be accessible online? This also serves as a first line of defence against hacking that can be built into every <code class="language-plaintext highlighter-rouge">Application</code> we write. It’s not a great defence, but while hackers are guessing the ID, they aren’t messing with our application.</p>
<p>You may wonder how we can be sure that the <code class="language-plaintext highlighter-rouge">ID</code> we give our <code class="language-plaintext highlighter-rouge">Application</code> hasn’t been used before by every Thomas, Richard, and Harold on the planet. The solution is rather ingenious and so simple, I wish I’d thought of it…</p>
<p>The <code class="language-plaintext highlighter-rouge">ID</code> starts with a reverse-order URL. And if you don’t own a URL you can use an email account or the full URL of any online code repository you have read/write privileges for.</p>
<p>Then, we tack on a unique string identifier. And as long as we keep track of which identifiers we give to which application, there should never be a problem.</p>
<p>Here are the choices I had when naming the example used here, each based on a URL I have access to and the unique string is just the name of the code file:</p>
<ul>
<li><strong>blog</strong>: com.gtkdcoding.app.app_02_barebones_with_id,</li>
<li><strong>email</strong>: com.gmail.gtkdcoding.app.app_02_barebones_with_id,</li>
<li><strong>repository</strong>: com.github.rontarrant.gtkdcoding.app.app_02_barebones_with_id</li>
</ul>
<p>You’ll note that I added an extra layer (.app) between the URL and the file name. It’s not strictly necessary, but it’s part of the site organization, so I threw it in there. However, the directory where you’ll find this code file is named <code class="language-plaintext highlighter-rouge">020_app</code>, not <code class="language-plaintext highlighter-rouge">app</code>. Why didn’t I use the full directory name?</p>
<p>Because we have…</p>
<h3 id="other-naming-conventions-we-need-to-follow">Other Naming Conventions We Need to Follow</h3>
<p>Interestingly enough, these conventions are similar to those used to name variables (as if we didn’t see <em>that</em> coming):</p>
<ul>
<li>the <code class="language-plaintext highlighter-rouge">ID</code> must be made up of at least two elements separated by a dot (element.element),</li>
<li>elements can be made up of:
<ul>
<li>alpha-numeric characters (a-z/A-Z, 0-9),</li>
<li>underscores (_), and</li>
<li>hyphens (-),</li>
</ul>
</li>
<li>the first character in an <code class="language-plaintext highlighter-rouge">ID</code> cannot be:
<ul>
<li>a digit (0-9), or</li>
<li>a dot (.),</li>
</ul>
</li>
<li>the first character in an <em>element</em> cannot be a digit (0-9),</li>
<li>putting two dots together (..) is not allowed,</li>
<li>the <code class="language-plaintext highlighter-rouge">ID</code> can’t start or end with a dot (.), and</li>
<li>the full length of the ID can’t be more than 255 characters.</li>
</ul>
<p>So, naming the ID looks like this:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">string</span> <span class="n">id</span> <span class="p">=</span> <span class="s">"com.gtkdcoding.app.app_02_barebones_with_id"</span><span class="p">;</span> <span class="c1">// rules</span>
</code></pre></div></div>
<p>Naming an <code class="language-plaintext highlighter-rouge">ID</code> string can be patterned after a <em>D</em>-language import statement. We can simply use the file or project name and substitute a dot for a directory separator. And when it’s time to update the project to a new version, just toss in a version number… as long as it’s done in such a way that we don’t violate any of the naming conventions.</p>
<p>All this takes place in our derived class, <code class="language-plaintext highlighter-rouge">MyApplication</code> (derived from <code class="language-plaintext highlighter-rouge">GtkApplication</code> which, if you remember, is an alias of <code class="language-plaintext highlighter-rouge">gtk.Application</code> and is, in turn, derived from <code class="language-plaintext highlighter-rouge">gio.Application</code>).</p>
<p>Now, let’s move on to…</p>
<h2 id="application-signals">Application Signals</h2>
<!-- 2, 3 -->
<!-- second occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
<div class="frame-header">
Results of this example:
</div>
<div class="frame-screenshot">
<figure>
<img id="img2" src="/images/screenshots/020_app/app_03_adding_signals.png" alt="Current example output" /> <!-- img# -->
<!-- Modal for screenshot -->
<div id="modal2" class="modal"> <!-- modal# -->
<span class="close2">×</span> <!-- close# -->
<img class="modal-content" id="img22" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal2"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img2"); // img#
var modalImg = document.getElementById("img22"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close2")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Current example output
</figcaption>
</figure>
</div>
<div class="frame-terminal">
<figure class="right">
<img id="img3" src="/images/screenshots/020_app/app_03_adding_signals_term.png" alt="Current example terminal output" /> <!-- img#, filename -->
<!-- Modal for terminal shot -->
<div id="modal3" class="modal"> <!-- modal# -->
<span class="close3">×</span> <!-- close# -->
<img class="modal-content" id="img33" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal3"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img3"); // img#
var modalImg = document.getElementById("img33"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close3")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Current example terminal output (click for enlarged view)
</figcaption>
</figure>
</div>
<div class="frame-footer"> <!--------- filename (below) ------------>
The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/020_app/app_03_adding_signals.d" target="_blank">here</a>.
</div>
</div>
<!-- end of snippet for second (2nd) occurrence of application and terminal screen shots on a single page -->
<p>The two most obvious signals that every <code class="language-plaintext highlighter-rouge">Application</code> might have are:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">startup</code>, and</li>
<li><code class="language-plaintext highlighter-rouge">shutdown</code>.</li>
</ul>
<p>So much might be done to prepare for running an <code class="language-plaintext highlighter-rouge">Application</code> or to clean up before exiting. A few things that come to mind are:</p>
<ul>
<li>loading and saving a configuration file,</li>
<li>on shutdown, check for unsaved changes and see if the user wants to save before exiting, or</li>
<li>on start-up, pop open a splash screen.</li>
</ul>
<p>Hooking them up is no biggie. We just do the same thing we always do:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">addOnStartup</span><span class="p">(&</span><span class="n">onStartup</span><span class="p">);</span>
<span class="n">addOnShutdown</span><span class="p">(&</span><span class="n">onShutdown</span><span class="p">);</span>
</code></pre></div></div>
<p>And the callback functions, in their simplest form, might look like:</p>
<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">void</span> <span class="n">onStartup</span><span class="p">(</span><span class="n">GioApplication</span> <span class="n">app</span><span class="p">)</span> <span class="c1">// non-advanced syntax</span>
<span class="p">{</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"triggered onStartup..."</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"\tThis is where you'd read a config file."</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// onStartup()</span>
<span class="kt">void</span> <span class="n">onShutdown</span><span class="p">(</span><span class="n">GioApplication</span> <span class="n">app</span><span class="p">)</span> <span class="c1">// non-advanced syntax</span>
<span class="p">{</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"triggered onShutdown..."</span><span class="p">);</span>
<span class="n">writeln</span><span class="p">(</span><span class="s">"\tThis is where you'd write a config file."</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// onShutdown()</span>
</code></pre></div></div>
<h2 id="conclusion">Conclusion</h2>
<p>And that wraps it up for another day. Next time, we’ll tackle <em>GIO</em>/<em>GTK</em> flags. Until then—to paraphrase Les Nessman of <em>WKRP</em>, may the good code be yours.</p>
<div class="blog-nav">
<div style="float: left;">
<a href="/posts/0112-gtk-gio-application-barebones.html">Previous: GTK GIO Applications - Introduction</a>
</div>
<div style="float: right;">
<a href="/posts/0114-gtk-gio-app-flags-and-cl-args.html">Next: GTK/GIO - Flags & the Command Line</a>
</div>
</div>]]></content><author><name>Ron Tarrant</name></author><category term="app" /><summary type="html"><![CDATA[Wherein we discover the role and naming conventions for application ID's and signals.]]></summary></entry><entry><title type="html">0112: GTK GIO Applications - Introduction</title><link href="http://localhost:4000/posts/0112-gtk-gio-application-barebones.html" rel="alternate" type="text/html" title="0112: GTK GIO Applications - Introduction" /><published>2021-09-03T00:00:00-04:00</published><updated>2021-09-03T00:00:00-04:00</updated><id>http://localhost:4000/posts/0112-gtk-gio-application-barebones</id><content type="html" xml:base="http://localhost:4000/posts/0112-gtk-gio-application-barebones.html"><![CDATA[<h2 id="after-the-hiatus">After the Hiatus</h2>
<p>It’s been more than a year since I made my last post on this blog. When I stopped posting last year, I was burned out, distracted by COVID-19, our tiny apartment was suddenly a hub of work activity for both of us, and I was still disheartened by the changes being made to <em>GTK</em> in version 4.</p>
<p>Now, I can see things a little more clearly… sort of. COVID-19 is still here and we may all go into (at least) one more round of lock-downs. But, other things are advancing…</p>
<p>My wife and I have both been double-vaccinated and we’ve worked out an arrangement whereby we can both work in this tiny apartment without driving each other up the wall.</p>
<p>Thirteen days ago, Mike Wey released GtkD 4, but the articles I’ve got on the go are all centred around GtkD 3.9. And frankly, I’m not sure I want to update to 4 because the <em>GTK</em> team dropped window position handling. Yes, it’s a small thing, but I see a problem with this…</p>
<p>The <em>GTK</em> team members believe window positions should be handled by the OS’s window manager. I do agree with them except for one thing: not all window managers remember window positions. I use three monitors, so this is kind of important to me. I like my applications to open in the last place I used them so I don’t have to search miles of screen real estate to find them.</p>
<p>So, with that in mind, I’d like to hear from you. Is anyone still interested in articles about GtkD 3.x? Please let me know in the comments below.</p>
<p>And with all that said, let’s dig into today’s article.</p>
<h2 id="0112-gtk-gio-applications---introduction">0112: GTK GIO Applications - Introduction</h2>
<p>Up ‘til now, every example has been built up from a <code class="language-plaintext highlighter-rouge">MainWindow</code> widget and a <code class="language-plaintext highlighter-rouge">Main</code> struct, both of which are instantiated in the standard entry point function, <code class="language-plaintext highlighter-rouge">main()</code>. (<em>Note: <code class="language-plaintext highlighter-rouge">TestRigWindow</code>—the actual object we’ve been instantiating in our examples—inherits from <code class="language-plaintext highlighter-rouge">MainWindow</code>, so it amounts to the same thing.</em>) But today, we’re looking at an alternative way of building applications, this time using the <em>GTK/GIO</em> <code class="language-plaintext highlighter-rouge">Application</code> class modules.</p>
<p>I’d like to point out that I didn’t stutter in that last sentence. There are two <code class="language-plaintext highlighter-rouge">Application</code> modules… the <em>GIO</em> <code class="language-plaintext highlighter-rouge">Application</code> is the parent class and the <em>GTK</em> class is derived from it. This can be a bit confusing when it comes time to write code because both modules need to be imported if we want to handle <em>GIO</em> signals. But, there’s a simple way to keep them straight, so let’s just dive in.</p>
<h2 id="why-application">Why Application?</h2>
<p>The <code class="language-plaintext highlighter-rouge">Application</code> is a more flexible framework for writing software. It doesn’t just give us the tools for building classic GUI-based software, it makes several other project types possible:</p>
<ul>
<li>a GUI front-end for a background service,</li>
<li>the background service itself,</li>
<li>remote applications controlled locally,</li>
<li>local applications controlled remotely, and</li>
<li>a GUI-less command line application (the kind intended to be run from a terminal).</li>
</ul>
<p>On top of that, a <em>GIO</em> <code class="language-plaintext highlighter-rouge">Application</code> has a signal/callback system that gives us all kinds of flexibility in how we start up our application.</p>
<p>Finally, it also gives us a system of flags we can use for all kinds of stuff including:</p>
<ol>
<li>designating the application as a service,</li>
<li>passing in parameters to modify the behaviour of the running software, or</li>
<li>react to the existence of environment variables on the computer where the application is running.</li>
</ol>
<h2 id="old-method-vs-new">Old Method vs. New</h2>
<p>The biggest difference between the <code class="language-plaintext highlighter-rouge">MainWindow</code> approach and this one is this…</p>
<p>In the <code class="language-plaintext highlighter-rouge">Application</code> paradigm, signals are used to associate callbacks with such things as <code class="language-plaintext highlighter-rouge">activate</code>, <code class="language-plaintext highlighter-rouge">startup</code>, and <code class="language-plaintext highlighter-rouge">shutdown</code>. In the paradigm we’ve been using ‘til now, <code class="language-plaintext highlighter-rouge">Main.init()</code>, <code class="language-plaintext highlighter-rouge">Main.run()</code>, and <code class="language-plaintext highlighter-rouge">Main.quit()</code> (respectively) take care of these things. Nothing new is going on here, but responsibility for application-level stuff has shifted from a <em>C</em>-style struct (<code class="language-plaintext highlighter-rouge">Main</code>) to a <em>D</em>-style object (<code class="language-plaintext highlighter-rouge">Application</code>).</p>
<h3 id="mainwindow-vs-applicationwindow">MainWindow vs. ApplicationWindow</h3>
<p>In the classical construction method, <code class="language-plaintext highlighter-rouge">MainWindow</code> acts as a top-level container for our program, but the <em>GTK/GIO</em> <code class="language-plaintext highlighter-rouge">Application</code> instead uses the <code class="language-plaintext highlighter-rouge">ApplicationWindow</code> as its primary UI container. They both inherit from <code class="language-plaintext highlighter-rouge">Window</code>, so we still get pretty much the same functionality. But the <em>GTK/GIO</em> <code class="language-plaintext highlighter-rouge">Application</code> construction method adds such things as window <code class="language-plaintext highlighter-rouge">ID</code>s, a pop-up help window for keyboard shortcuts, and a mechanism to handle how and when a <code class="language-plaintext highlighter-rouge">Menu</code> or <code class="language-plaintext highlighter-rouge">Menubar</code> is displayed. More on these as we go along, but for now, let’s dig into a barebones example…</p>
<h2 id="working-with-giogtk-applications">Working with GIO/GTK Applications</h2>
<!-- 0, 1 -->
<!-- first occurrence of application and terminal screen shots on a single page -->
<div class="screenshot-frame">
<div class="frame-header">
Results of this example:
</div>
<div class="frame-screenshot">
<figure>
<img id="img0" src="/images/screenshots/020_app/app_01.png" alt="Current example output" /> <!-- img# -->
<!-- Modal for screenshot -->
<div id="modal0" class="modal"> <!-- modal# -->
<span class="close0">×</span> <!-- close# -->
<img class="modal-content" id="img00" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal
var modal = document.getElementById("modal0"); // modal#
// Get the image and insert it inside the modal - use its "alt" text as a caption
var img = document.getElementById("img0"); // img#
var modalImg = document.getElementById("img00"); // img##
var captionText = document.getElementById("caption");
img.onclick = function()
{
modal.style.display = "block";
modalImg.src = this.src;
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close0")[0]; // close#
// When the user clicks on <span> (x), close the modal
span.onclick = function()
{
modal.style.display = "none";
}
</script>
<figcaption>
Current example output
</figcaption>
</figure>
</div>
<div class="frame-terminal">
<figure class="right">
<img id="img1" src="/images/screenshots/020_app/app_01_term.png" alt="Current example terminal output" /> <!-- img#, filename -->
<!-- Modal for terminal shot -->
<div id="modal1" class="modal"> <!-- modal# -->
<span class="close1">×</span> <!-- close# -->
<img class="modal-content" id="img11" /> <!-- img## -->
<div id="caption"></div>
</div>
<script>
// Get the modal