1 /*
2* Copyright (c) 2018 (https://github.com/phase1geo/Minder)
3*
4* This program is free software; you can redistribute it and/or
5* modify it under the terms of the GNU General Public
6* License as published by the Free Software Foundation; either
7* version 2 of the License, or (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12* General Public License for more details.
13*
14* You should have received a copy of the GNU General Public
15* License along with this program; if not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17* Boston, MA 02110-1301 USA
18*
19* Authored by: Trevor Williams <phase1geo@gmail.com>
20*/
21
22using Gtk;
23using Gdk;
24using GLib;
25
26public class Minder : Granite.Application {
27
28  private const string INTERFACE_SCHEMA = "org.gnome.desktop.interface";
29
30  private static bool          show_version = false;
31  private static string?       open_file    = null;
32  private static bool          new_file     = false;
33  private static bool          testing      = false;
34  private        MainWindow    appwin;
35  private        GLib.Settings iface_settings;
36
37  public  static GLib.Settings settings;
38  public  static string        version = "1.13.1";
39
40  public Minder () {
41
42    Object( application_id: "com.github.phase1geo.minder", flags: ApplicationFlags.HANDLES_OPEN );
43
44    startup.connect( start_application );
45    open.connect( open_files );
46
47  }
48
49  /* First method called in the startup process */
50  private void start_application() {
51
52    /* Initialize the settings */
53    settings = new GLib.Settings( "com.github.phase1geo.minder" );
54
55    /* Add the application-specific icons */
56    weak IconTheme default_theme = IconTheme.get_default();
57    default_theme.add_resource_path( "/com/github/phase1geo/minder" );
58
59    /* Create the main window */
60    appwin = new MainWindow( this, settings );
61
62    /* Load the tab data */
63    appwin.load_tab_state();
64
65    /* Handle any changes to the position of the window */
66    appwin.configure_event.connect(() => {
67      int root_x, root_y;
68      int size_w, size_h;
69      appwin.get_position( out root_x, out root_y );
70      appwin.get_size( out size_w, out size_h );
71      settings.set_int( "window-x", root_x );
72      settings.set_int( "window-y", root_y );
73      settings.set_int( "window-w", size_w );
74      settings.set_int( "window-h", size_h );
75      return( false );
76    });
77
78    /* Initialize desktop interface settings */
79    string[] names = {"font-name", "text-scaling-factor"};
80    iface_settings = new GLib.Settings( INTERFACE_SCHEMA );
81    foreach( string name in names ) {
82      iface_settings.changed[name].connect(() => {
83        Timeout.add( 500, () => {
84          appwin.update_node_sizes();
85          return( Source.REMOVE );
86        });
87      });
88    }
89
90  }
91
92  /* Called whenever files need to be opened */
93  private void open_files( File[] files, string hint ) {
94    hold();
95    foreach( File open_file in files ) {
96      var file = open_file.get_path();
97      if( !appwin.open_file( file ) ) {
98        stdout.printf( _( "ERROR:  Unable to open file '%s'\n" ), file );
99      }
100    }
101    Gtk.main();
102    release();
103  }
104
105  /* Called if we have no files to open */
106  protected override void activate() {
107    hold();
108    if( new_file ) {
109      appwin.do_new_file();
110    }
111    Gtk.main();
112    release();
113  }
114
115  /* Parse the command-line arguments */
116  private void parse_arguments( ref unowned string[] args ) {
117
118    var context = new OptionContext( "- Minder Options" );
119    var options = new OptionEntry[4];
120
121    /* Create the command-line options */
122    options[0] = {"version", 0, 0, OptionArg.NONE, ref show_version, _( "Display version number" ), null};
123    options[1] = {"new", 'n', 0, OptionArg.NONE, ref new_file, _( "Starts Minder with a new file" ), null};
124    options[2] = {"run-tests", 0, 0, OptionArg.NONE, ref testing, _( "Run testing" ), null};
125    options[3] = {null};
126
127    /* Parse the arguments */
128    try {
129      context.set_help_enabled( true );
130      context.add_main_entries( options, null );
131      context.parse( ref args );
132    } catch( OptionError e ) {
133      stdout.printf( _( "ERROR: %s\n" ), e.message );
134      stdout.printf( _( "Run '%s --help' to see valid options\n" ), args[0] );
135      Process.exit( 1 );
136    }
137
138    /* If the version was specified, output it and then exit */
139    if( show_version ) {
140      stdout.printf( version + "\n" );
141      Process.exit( 0 );
142    }
143
144    /* If we see files on the command-line */
145    if( args.length >= 2 ) {
146      open_file = args[1];
147    }
148
149  }
150
151  /* Main routine which gets everything started */
152  public static int main( string[] args ) {
153
154    var app = new Minder();
155    app.parse_arguments( ref args );
156
157    if( testing ) {
158      Gtk.init( ref args );
159      var testing = new App.Tests.Testing( args );
160      Idle.add(() => {
161        testing.run();
162        Gtk.main_quit();
163        return( false );
164      });
165      Gtk.main();
166      return( 0 );
167    } else {
168      return( app.run( args ) );
169    }
170
171  }
172
173}
174
175