~elementary-apps/pantheon-terminal/master

« back to all changes in this revision

Viewing changes to src/main.vala

  • Committer: kekun.plazas@laposte.net
  • Date: 2011-06-19 15:34:04 UTC
  • Revision ID: git-v1:03007337b8d45983a3be21b8d295b5af68a60b04
CMake port in progress

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//  
 
2
//  Copyright (C) 2011 Adrien Plazas
 
3
// 
 
4
//  This program is free software: you can redistribute it and/or modify
 
5
//  it under the terms of the GNU General Public License as published by
 
6
//  the Free Software Foundation, either version 3 of the License, or
 
7
//  (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
 
12
//  GNU General Public License for more details.
 
13
// 
 
14
//  You should have received a copy of the GNU General Public License
 
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
16
// 
 
17
// 
 
18
//  Authors:
 
19
//      Adrien Plazas <kekun.plazas@laposte.net>
 
20
//  Artists:
 
21
//      Daniel Foré <daniel@elementaryos.org>
 
22
// 
 
23
 
 
24
/* Use default system font (tag FIXME)
 
25
 * Set preferences via GSettings ?
 
26
 * Do not focus on buttons
 
27
 * Improve window resize (is it useful ?)
 
28
 * Add right click menu with: copy, paste, preferences?, about
 
29
 * Notify with system bubbles if the window is not focused (tag FIXME)
 
30
 * Set Dan correctly as the artist
 
31
 */
 
32
 
 
33
using Gtk;
 
34
using Vte;
 
35
using Pango;
 
36
using Notify;
 
37
 
 
38
private class PantheonTerminal : Window
 
39
{
 
40
    Notebook notebook;
 
41
    FontDescription font;
 
42
    Gdk.Color bgcolor;
 
43
    Gdk.Color fgcolor;
 
44
    
 
45
    bool window_focus = false;
 
46
    
 
47
    Notify.Notification notification;
 
48
    
 
49
        private PantheonTerminal()
 
50
        {
 
51
        Gtk.Settings.get_default().gtk_application_prefer_dark_theme = true;
 
52
        set_title("Terminal");
 
53
        default_width = 640;
 
54
        default_height = 400;
 
55
        destroy.connect(close);
 
56
        
 
57
        // Check if the window have the focus
 
58
        focus_in_event.connect(() => { window_focus = true; return false; });
 
59
        focus_out_event.connect(() => { window_focus = false; return false; });
 
60
                
 
61
        notebook = new Notebook();
 
62
                var left_box = new HBox(false, 0);
 
63
        var right_box = new HBox(false, 0);
 
64
        left_box.show();
 
65
        right_box.show();
 
66
        notebook.set_action_widget(left_box, PackType.START);
 
67
        notebook.set_action_widget(right_box, PackType.END);
 
68
        notebook.set_scrollable(true);
 
69
        add(notebook);
 
70
        
 
71
        left_box.set_size_request(10, 0);
 
72
        
 
73
        // Set "New tab" button
 
74
        var add_button = new Button();
 
75
        add_button.set_image(new Image.from_stock(Stock.ADD, IconSize.MENU));
 
76
        add_button.show();
 
77
        add_button.set_relief(ReliefStyle.NONE);
 
78
        add_button.set_tooltip_text("Open a new tab");
 
79
        add_button.clicked.connect(new_tab);
 
80
        right_box.pack_start(add_button, false, false, 0);
 
81
                
 
82
        // Get the system's style
 
83
        realize();
 
84
        font = FontDescription.from_string(system_font());
 
85
        bgcolor = get_style().bg[StateType.NORMAL];
 
86
        fgcolor = get_style().fg[StateType.NORMAL];
 
87
                        
 
88
                // Try to set the icon FIXME
 
89
        Gdk.Pixbuf icon = new Gdk.Pixbuf(Gdk.Colorspace.RGB, true, 8, 1, 1);
 
90
        try { IconTheme.get_default().load_icon("terminal", 16, IconLookupFlags.FORCE_SVG); } catch (Error er) {}
 
91
                try { set_icon(icon); } catch(Error er) {}
 
92
        
 
93
                show_all();
 
94
        new_tab();
 
95
        }
 
96
    
 
97
    static string system_font()
 
98
    {
 
99
        string font_name = null;
 
100
        /* Wait for GNOME 3 FIXME
 
101
         * var settings = new GLib.Settings("org.gnome.desktop.interface");
 
102
         * font_name = settings.get_string("monospace-font-name");
 
103
         */
 
104
        font_name = "Droid Sans Mono 10";
 
105
        return font_name;
 
106
    }
 
107
    
 
108
    private void new_tab()
 
109
    {
 
110
        // Set up terminal
 
111
        var t = new TerminalWithNotification();
 
112
        t.fork_command(null,null,null,null, true, true,true);
 
113
        
 
114
        // Test the "task_over" signal
 
115
        t.task_over.connect(() => {stdout.printf("task_over\n");});
 
116
 
 
117
        t.show();
 
118
        
 
119
        // Create a new tab with the terminal
 
120
        var tab = new TabWithCloseButton("Terminal");
 
121
        notebook.insert_page(t, tab, notebook.get_current_page() + 1);
 
122
        notebook.next_page();
 
123
        notebook.set_tab_reorderable(t, true);
 
124
        
 
125
        // Set connections
 
126
        tab.clicked.connect(() => { notebook.remove(t); });
 
127
        t.window_title_changed.connect(() => { tab.set_text(t.get_window_title()); });
 
128
        notebook.switch_page.connect((page, page_num) => { if (notebook.page_num(t) == (int) page_num) tab.set_notification(false); });
 
129
        focus_in_event.connect(() => { if (notebook.page_num(t) == notebook.get_current_page()) tab.set_notification(false); return false; });
 
130
        
 
131
        // If a task is over
 
132
        t.task_over.connect(() => {
 
133
            if (notebook.page_num(t) != notebook.get_current_page() || !window_focus)
 
134
                tab.set_notification(true);
 
135
            if (!window_focus)
 
136
//~                 notification = (Notify.Notification)GLib.Object.new (
 
137
//~                     typeof (Notify.Notification),
 
138
//~                     "summary", "sum",
 
139
//~                     "body", "message",
 
140
//~                     "icon-name", "");
 
141
                    // Notify OSD
 
142
//~                 notification = new Notification("test", "test", "test");
 
143
//~                 try { notification.show(); }
 
144
//~                 catch {}
 
145
                    
 
146
                stdout.printf("focus\n");
 
147
            });
 
148
        
 
149
        // Set up style
 
150
        t.set_font(font);
 
151
        t.set_color_background(bgcolor);
 
152
        t.set_color_foreground(fgcolor);
 
153
    }
 
154
    
 
155
    private void close()
 
156
    {
 
157
        Gtk.main_quit();
 
158
    }
 
159
    
 
160
        private static void main(string[] args)
 
161
        {
 
162
                Gtk.init(ref args);
 
163
                new PantheonTerminal();
 
164
                Gtk.main();
 
165
        }
 
166
}
 
167
 
 
168
public class TerminalWithNotification : Terminal
 
169
{
 
170
    public signal void task_over();
 
171
    
 
172
    long last_row_count = 0;
 
173
    long last_column_count = 0;
 
174
    
 
175
    public TerminalWithNotification()
 
176
    {
 
177
        set_size_request(320, 200);
 
178
        window_title_changed.connect(check_for_notification);
 
179
    }
 
180
    
 
181
    private void check_for_notification()
 
182
    {
 
183
        /* Curently I use this trick to know if a task is over, the drawnback is
 
184
         * that when the window is resized and a notification should be received,
 
185
         * the user will not be notified.
 
186
         */
 
187
        if (get_row_count() == last_row_count && get_column_count() == last_column_count)
 
188
            task_over();
 
189
        last_row_count = get_row_count();
 
190
        last_column_count = get_column_count();
 
191
    }
 
192
}
 
193
 
 
194
public class TabWithCloseButton : HBox
 
195
{
 
196
    public signal void clicked();
 
197
    
 
198
    private Button button;
 
199
    private Label label;
 
200
    private string text;
 
201
    bool notification = false;
 
202
    
 
203
    public TabWithCloseButton(string text)
 
204
    {
 
205
        this.text = text;
 
206
        
 
207
        // Button
 
208
        button = new Button();
 
209
        button.set_image(new Image.from_stock(Stock.CLOSE, IconSize.MENU));
 
210
        button.show();
 
211
        button.set_relief(ReliefStyle.NONE);
 
212
        button.clicked.connect(() => { clicked(); });
 
213
        
 
214
        // Label
 
215
        label = new Label(text);
 
216
        label.show();
 
217
        
 
218
        // Pack the elements
 
219
        pack_start(button, false, true, 0);
 
220
        pack_end(label, true, true, 0);
 
221
        show();
 
222
    }
 
223
    
 
224
    public void set_notification(bool notification)
 
225
    {
 
226
        this.notification = notification;
 
227
        if (notification)
 
228
        { label.set_markup("<span color=\"#18a0c0\">"+text+"</span>"); }
 
229
        else
 
230
        { label.set_markup(text); }
 
231
    }
 
232
    
 
233
    public void set_text(string text)
 
234
    {
 
235
        this.text = text;
 
236
        set_notification(notification);
 
237
    }
 
238
}