0114: GTK/GIO Application Flags and Command Line Arguments
Today we’ll dig into passing command line arguments to a GTK/GIO application and start looking at the built-in mechanism that handles them.
The Arguments
As mentioned last time, command-line arguments are passed along to the GIO Application
—a class object rather than the Main
C-style struct we’ve used all along—and packed into an array. The flow of these arguments is:
- the user types the arguments,
- the class initializer method then:
- pulls them in —
this(string[] args)
, - passes them to the
GtkApplication.run()
method —run(args)
, and
- pulls them in —
- they’re stored in an
ApplicationCommandLine
object.
From there, we pull them out in our onCommandLine()
method (which we’ll look at momentarily).
Now let’s take a gander at the initialization method in full:
this(string[] args)
{
super(id, flags);
addOnActivate(&onActivate);
addOnCommandLine(&onCommandLine);
addOnStartup(&onStartup);
addOnShutdown(&onShutdown);
writeln("registration before: ", registration);
registration = register(null);
writeln("registration after: ", registration);
run(args);
} // this()
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.
Now, before we dig in further, I want to point out one other thing we need to take care of when deriving our MyApplication
class from GtkApplication
…
We need to tell GTK/GIO that we’re intending to handle command-line arguments and to do this, we declare a class attribute in the preamble:
ApplicationFlags flags = ApplicationFlags.HANDLES_COMMAND_LINE;
It’s an extra step compared to doing things the way we’re used to.
Parsing, Parsing, Over the Bounding Command-line
Now that GIO 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:
int onCommandLine(ApplicationCommandLine acl, GioApplication app)
{
int exitStatus = 0;
string[] args = acl.getArguments();
int[] dimensions = [0, 0];
writeln("triggered onCommandLine...");
// remove the application name from the string of args
args = args.remove(0);
writeln("\tcommandline args: ", args);
writeln("\targs.length: ", args.length);
if(args.length == 0)
{
writeln("\tno args");
activate(null);
}
else
{
for(int i; i < args.length; i += 2)
{
string arg = args[i];
switch(arg)
{
case "width":
dimensions[0] = to!int(args[i + 1]);
break;
case "height":
dimensions[1] = to!int(args[i + 1]);
break;
default:
writeln("arg: ", arg);
writeln("arg: ", to!string(args[i + 1]));
break;
}
}
activate(dimensions);
}
return(exitStatus);
} // onCommandLine()
Note the method arguments:
ApplicationCommandLine acl
, andGioApplication app
.
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 ApplicationCommandLine
class which is specifically designed for that purpose. Here in the parser method is where we retrieve them and get down to business.
In short (skipping down to the if
/else
), what we do here is:
- get rid of the application name (which, you’ll remember, is always retrieved along with the arguments) by
remove()
ing the zeroth element of theargs
array, - step through the remaining args two at a time,
- check each against a pre-determined set of args we’re expecting (
“width”
and“height”
in this case), - do a look-ahead to the next argument to get a value, and
- calling the
activate()
method, passing in the width and height we’ve captured from the command line.
The activate() Method
GIO has a default activate()
method which gets called unless we override it. Here, that’s exactly what we’re doing.
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 width
and height
, each followed by a number, the window has a default size, the dimensions of which are object attributes in the preamble to the AppWindow
class.
Conclusion
Because of space constraints, I’ve skimmed over a few things, so if you have questions, please ask them in the comments below.
Next time, we’ll carry on in this same vein, but turn to the HANDLES_OPEN
flag to see how a list of files can be opened using these methods.
Until then, just remember Howard’s immortal words: “There’s no place for truth on the Internet.”
Comments? Questions? Observations?
Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
- come on over to the D Language Forum and look for one of the gtkDcoding announcement posts,
- drop by the GtkD Forum,
- follow the link below to email me, or
- go to the gtkDcoding Facebook page.
You can also subscribe via RSS so you won't miss anything. Thank you very much for dropping by.
© Copyright 2024 Ron Tarrant