~ubuntu-branches/ubuntu/natty/geany/natty

« back to all changes in this revision

Viewing changes to src/notebook.c

  • Committer: Bazaar Package Importer
  • Author(s): Gauvain Pocentek
  • Date: 2009-01-01 18:40:50 UTC
  • mfrom: (1.1.8 upstream) (3.1.2 experimental)
  • Revision ID: james.westby@ubuntu.com-20090101184050-u635kualu7amyt4a
Tags: 0.15-1ubuntu1
* Merge from debian experimental, remaining change:
  - patches/20_add_debdiff_as_diff_type.dpatch: Also recognize .dpatch files
    as diff's
  - debian/geany.xpm: Replace icon with a .xpm of the new one

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *      along with this program; if not, write to the Free Software
19
19
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
20
 *
21
 
 * $Id: notebook.c 2375 2008-03-21 13:05:47Z ntrel $
 
21
 * $Id: notebook.c 3017 2008-09-28 15:17:00Z eht16 $
22
22
 */
23
23
 
24
24
/*
27
27
 
28
28
#include "geany.h"
29
29
#include "notebook.h"
30
 
#include "prefs.h"
31
30
#include "document.h"
 
31
#include "editor.h"
 
32
#include "documentprivate.h"
32
33
#include "ui_utils.h"
33
34
#include "treeviews.h"
34
35
#include "support.h"
77
78
static void setup_tab_dnd(void);
78
79
 
79
80
 
80
 
static void focus_sci(GtkWidget *widget, gpointer user_data)
81
 
{
82
 
        gint idx = document_get_cur_idx();
83
 
 
84
 
        if (! DOC_IDX_VALID(idx)) return;
85
 
 
86
 
        gtk_widget_grab_focus(GTK_WIDGET(doc_list[idx].sci));
 
81
static gboolean focus_sci(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
 
82
{
 
83
        GeanyDocument *doc = document_get_current();
 
84
 
 
85
        if (doc != NULL)
 
86
                gtk_widget_grab_focus(GTK_WIDGET(doc->editor->sci));
 
87
 
 
88
        return FALSE;
 
89
}
 
90
 
 
91
 
 
92
static gboolean gtk_notebook_show_arrows(GtkNotebook *notebook)
 
93
{
 
94
        return notebook->scrollable;
 
95
#if 0
 
96
        /* To get this working we would need to define at least the first two fields of
 
97
         * GtkNotebookPage since it is a private field. The better way would be to
 
98
         * subclass GtkNotebook.
 
99
struct _FakeGtkNotebookPage
 
100
{
 
101
        GtkWidget *child;
 
102
        GtkWidget *tab_label;
 
103
};
 
104
 */
 
105
        gboolean show_arrow = FALSE;
 
106
        GList *children;
 
107
 
 
108
        if (! notebook->scrollable)
 
109
                return FALSE;
 
110
 
 
111
        children = notebook->children;
 
112
        while (children)
 
113
        {
 
114
                struct _FakeGtkNotebookPage *page = children->data;
 
115
 
 
116
                if (page->tab_label && ! gtk_widget_get_child_visible(page->tab_label))
 
117
                        show_arrow = TRUE;
 
118
 
 
119
                children = children->next;
 
120
        }
 
121
        return show_arrow;
 
122
#endif
 
123
}
 
124
 
 
125
 
 
126
static gboolean is_position_on_tab_bar(GtkNotebook *notebook, GdkEventButton *event)
 
127
{
 
128
        GtkWidget *page;
 
129
        GtkWidget *tab;
 
130
        GtkWidget *nb;
 
131
        GtkPositionType tab_pos;
 
132
        gint scroll_arrow_hlength, scroll_arrow_vlength;
 
133
        gdouble x, y;
 
134
 
 
135
        page = gtk_notebook_get_nth_page(notebook, 0);
 
136
        g_return_val_if_fail(page != NULL, FALSE);
 
137
 
 
138
        tab = gtk_notebook_get_tab_label(notebook, page);
 
139
        g_return_val_if_fail(tab != NULL, FALSE);
 
140
 
 
141
        tab_pos = gtk_notebook_get_tab_pos(notebook);
 
142
        nb = GTK_WIDGET(notebook);
 
143
 
 
144
#if GTK_CHECK_VERSION(2, 10, 0)
 
145
        gtk_widget_style_get(GTK_WIDGET(notebook), "scroll-arrow-hlength", &scroll_arrow_hlength,
 
146
                "scroll-arrow-vlength", &scroll_arrow_vlength, NULL);
 
147
#else
 
148
        scroll_arrow_hlength = scroll_arrow_vlength = 16;
 
149
#endif
 
150
 
 
151
        if (! gdk_event_get_coords((GdkEvent*) event, &x, &y))
 
152
        {
 
153
                x = event->x;
 
154
                y = event->y;
 
155
        }
 
156
 
 
157
        switch (tab_pos)
 
158
        {
 
159
                case GTK_POS_TOP:
 
160
                case GTK_POS_BOTTOM:
 
161
                {
 
162
                        if (event->y >= 0 && event->y <= tab->allocation.height)
 
163
                        {
 
164
                                if (! gtk_notebook_show_arrows(notebook) || (
 
165
                                        x > scroll_arrow_hlength &&
 
166
                                        x < nb->allocation.width - scroll_arrow_hlength))
 
167
                                        return TRUE;
 
168
                        }
 
169
                        break;
 
170
                }
 
171
                case GTK_POS_LEFT:
 
172
                case GTK_POS_RIGHT:
 
173
                {
 
174
                        if (event->x >= 0 && event->x <= tab->allocation.width)
 
175
                        {
 
176
                                if (! gtk_notebook_show_arrows(notebook) || (
 
177
                                        y > scroll_arrow_vlength &&
 
178
                                        y < nb->allocation.height - scroll_arrow_vlength))
 
179
                                        return TRUE;
 
180
                        }
 
181
                }
 
182
        }
 
183
 
 
184
        return FALSE;
 
185
}
 
186
 
 
187
 
 
188
static gboolean notebook_tab_bar_click_cb(GtkWidget *widget, GdkEventButton *event,
 
189
                                                                                  gpointer user_data)
 
190
{
 
191
        if (event->type == GDK_2BUTTON_PRESS)
 
192
        {
 
193
                /* accessing ::event_window is a little hacky but we need to make sure the click
 
194
                 * was in the tab bar and not inside the child */
 
195
                if (event->window != GTK_NOTEBOOK(main_widgets.notebook)->event_window)
 
196
                        return FALSE;
 
197
 
 
198
                if (is_position_on_tab_bar(GTK_NOTEBOOK(widget), event))
 
199
                {
 
200
                        document_new_file(NULL, NULL, NULL);
 
201
                        return TRUE;
 
202
                }
 
203
        }
 
204
        return FALSE;
87
205
}
88
206
 
89
207
 
90
208
void notebook_init()
91
209
{
 
210
        g_signal_connect_after(main_widgets.notebook, "button-press-event",
 
211
                G_CALLBACK(notebook_tab_bar_click_cb), NULL);
 
212
 
92
213
        /* focus the current document after clicking on a tab */
93
 
        g_signal_connect_after(G_OBJECT(app->notebook), "button-release-event",
 
214
        g_signal_connect_after(main_widgets.notebook, "button-release-event",
94
215
                G_CALLBACK(focus_sci), NULL);
95
216
 
96
 
        g_signal_connect(G_OBJECT(app->notebook), "drag-data-received",
 
217
        g_signal_connect(main_widgets.notebook, "drag-data-received",
97
218
                G_CALLBACK(on_window_drag_data_received), NULL);
98
219
 
99
220
        setup_tab_dnd();
102
223
 
103
224
static void setup_tab_dnd()
104
225
{
105
 
        GtkWidget *notebook = app->notebook;
 
226
        GtkWidget *notebook = main_widgets.notebook;
106
227
 
107
228
        /* Due to a segfault with manual tab DnD setup on GTK 2.10, we must
108
229
        *  use the built in gtk_notebook_set_tab_reorderable from GTK 2.10.
112
233
        if (gtk_check_version(2, 10, 0) == NULL) /* null means version ok */
113
234
        {
114
235
#if GTK_CHECK_VERSION(2, 10, 0)
115
 
                g_signal_connect(G_OBJECT(notebook), "page-reordered",
116
 
                        G_CALLBACK(notebook_page_reordered_cb), NULL);
 
236
                g_signal_connect(notebook, "page-reordered", G_CALLBACK(notebook_page_reordered_cb), NULL);
117
237
#endif
118
238
                return;
119
239
        }
120
240
 
121
241
        /* Set up drag movement callback */
122
 
        g_signal_connect(G_OBJECT(notebook), "drag-motion",
123
 
                G_CALLBACK(notebook_drag_motion_cb), NULL);
 
242
        g_signal_connect(notebook, "drag-motion", G_CALLBACK(notebook_drag_motion_cb), NULL);
124
243
 
125
244
        /* There is a bug on GTK 2.6 with drag reordering of notebook tabs.
126
245
         * Clicking (not dragging) on a notebook tab, then making a selection in the
135
254
        {
136
255
                /* workaround GTK+2.6 drag start bug when over sci widget: */
137
256
                gtk_widget_add_events(notebook, GDK_POINTER_MOTION_MASK);
138
 
                g_signal_connect(G_OBJECT(notebook), "motion-notify-event",
 
257
                g_signal_connect(notebook, "motion-notify-event",
139
258
                        G_CALLBACK(notebook_motion_notify_event_cb), NULL);
140
259
        }
141
260
#endif
158
277
        gpointer user_data)
159
278
{
160
279
        static gboolean drag_enabled = TRUE; /* stores current state */
161
 
        GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(app->notebook),
162
 
                        gtk_notebook_get_current_page(GTK_NOTEBOOK(app->notebook)));
 
280
        GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(main_widgets.notebook),
 
281
                        gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook)));
163
282
 
164
283
        if (page == NULL || event->x < 0 || event->y < 0) return FALSE;
165
284
 
261
380
                }
262
381
 
263
382
                /* subtract notebook pos to remove possible border padding */
264
 
                max_x = tab->allocation.x + tab->allocation.width -
265
 
                        GTK_WIDGET(notebook)->allocation.x;
266
 
                max_y = tab->allocation.y + tab->allocation.height -
267
 
                        GTK_WIDGET(notebook)->allocation.y;
 
383
                max_x = tab->allocation.x + tab->allocation.width - GTK_WIDGET(notebook)->allocation.x;
 
384
                max_y = tab->allocation.y + tab->allocation.height - GTK_WIDGET(notebook)->allocation.y;
268
385
 
269
 
                if (((tab_pos == GTK_POS_TOP)
270
 
                        || (tab_pos == GTK_POS_BOTTOM))
271
 
                        &&(x<=max_x)) return page_num;
272
 
                else if (((tab_pos == GTK_POS_LEFT)
273
 
                        || (tab_pos == GTK_POS_RIGHT))
274
 
                        && (y<=max_y)) return page_num;
 
386
                if (((tab_pos == GTK_POS_TOP) || (tab_pos == GTK_POS_BOTTOM)) && (x<=max_x))
 
387
                        return page_num;
 
388
                else if (((tab_pos == GTK_POS_LEFT) || (tab_pos == GTK_POS_RIGHT)) && (y<=max_y))
 
389
                        return page_num;
275
390
 
276
391
                page_num++;
277
392
        }
279
394
}
280
395
 
281
396
 
282
 
/* call this after the number of tabs in app->notebook changes. */
 
397
/* call this after the number of tabs in main_widgets.notebook changes. */
283
398
static void tab_count_changed(void)
284
399
{
285
 
        switch (gtk_notebook_get_n_pages(GTK_NOTEBOOK(app->notebook)))
 
400
        switch (gtk_notebook_get_n_pages(GTK_NOTEBOOK(main_widgets.notebook)))
286
401
        {
287
402
                case 0:
288
403
                /* Enables DnD for dropping files into the empty notebook widget */
289
 
                gtk_drag_dest_set(app->notebook, GTK_DEST_DEFAULT_ALL,
 
404
                gtk_drag_dest_set(main_widgets.notebook, GTK_DEST_DEFAULT_ALL,
290
405
                        files_drop_targets,     G_N_ELEMENTS(files_drop_targets),
291
406
                        GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK);
292
407
                break;
295
410
                /* Disables DnD for dropping files into the notebook widget and enables the DnD for moving file
296
411
                 * tabs. Files can still be dropped into the notebook widget because it will be handled by the
297
412
                 * active Scintilla Widget (only dropping to the tab bar is not possible but it should be ok) */
298
 
                gtk_drag_dest_set(app->notebook, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
 
413
                gtk_drag_dest_set(main_widgets.notebook, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
299
414
                        drag_targets, G_N_ELEMENTS(drag_targets), GDK_ACTION_MOVE);
300
415
                break;
301
416
        }
302
417
}
303
418
 
304
 
gboolean notebook_tab_label_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
 
419
 
 
420
static gboolean notebook_tab_label_cb(GtkWidget *widget, GdkEventButton *event, gpointer data)
305
421
{
306
422
        /* toggle additional widgets on double click */
307
423
        if (event->type == GDK_2BUTTON_PRESS)
 
424
        {
308
425
                on_menu_toggle_all_additional_widgets1_activate(NULL, NULL);
 
426
                return TRUE; /* stop other handlers like notebook_tab_bar_click_cb() */
 
427
        }
309
428
        /* close tab on middle click */
310
429
        if (event->button == 2)
311
 
                document_remove(gtk_notebook_page_num(GTK_NOTEBOOK(app->notebook), GTK_WIDGET(user_data)));
 
430
        {
 
431
                document_remove_page(gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
 
432
                        GTK_WIDGET(data)));
 
433
                return TRUE; /* stop other handlers like notebook_tab_bar_click_cb() */
 
434
        }
312
435
 
313
436
        return FALSE;
314
437
}
315
438
 
316
439
 
317
440
/* Returns page number of notebook page, or -1 on error */
318
 
gint notebook_new_tab(gint doc_idx)
 
441
gint notebook_new_tab(GeanyDocument *this)
319
442
{
320
443
        GtkWidget *hbox, *ebox;
321
444
        gint tabnum;
322
445
        gchar *title;
323
 
        document *this = &(doc_list[doc_idx]);
324
446
        GtkWidget *page;
325
447
 
326
 
        g_return_val_if_fail(doc_idx >= 0 && this != NULL, -1);
327
 
 
328
 
        page = GTK_WIDGET(this->sci);
329
 
        title = g_path_get_basename(DOC_FILENAME(doc_idx));
330
 
 
331
 
        this->tab_label = gtk_label_new(title);
 
448
        g_return_val_if_fail(this != NULL, -1);
 
449
 
 
450
        page = GTK_WIDGET(this->editor->sci);
 
451
        title = g_path_get_basename(DOC_FILENAME(this));
 
452
 
 
453
        this->priv->tab_label = gtk_label_new(title);
332
454
 
333
455
        ebox = gtk_event_box_new();
334
456
        GTK_WIDGET_SET_FLAGS(ebox, GTK_NO_WINDOW);
335
 
        g_signal_connect(G_OBJECT(ebox), "button-press-event",
336
 
                G_CALLBACK(notebook_tab_label_cb), page);
 
457
        g_signal_connect(ebox, "button-press-event", G_CALLBACK(notebook_tab_label_cb), page);
337
458
 
338
459
        hbox = gtk_hbox_new(FALSE, 2);
339
 
        gtk_container_add(GTK_CONTAINER(ebox), this->tab_label);
 
460
        gtk_container_add(GTK_CONTAINER(ebox), this->priv->tab_label);
340
461
        gtk_box_pack_start(GTK_BOX(hbox), ebox, FALSE, FALSE, 0);
341
462
 
342
 
        if (prefs.show_tab_cross)
 
463
        if (file_prefs.show_tab_cross)
343
464
        {
344
465
                GtkWidget *image, *btn, *align;
345
466
                GtkRcStyle *rcstyle;
367
488
 
368
489
                gtk_box_pack_start(GTK_BOX(hbox), align, TRUE, TRUE, 0);
369
490
 
370
 
                g_signal_connect(G_OBJECT(btn), "clicked",
371
 
                        G_CALLBACK(notebook_tab_close_clicked_cb), page);
 
491
                g_signal_connect(btn, "clicked", G_CALLBACK(notebook_tab_close_clicked_cb), page);
372
492
        }
373
493
 
374
494
        gtk_widget_show_all(hbox);
375
495
 
376
 
        this->tabmenu_label = gtk_label_new(title);
377
 
        gtk_misc_set_alignment(GTK_MISC(this->tabmenu_label), 0.0, 0);
 
496
        this->priv->tabmenu_label = gtk_label_new(title);
 
497
        gtk_misc_set_alignment(GTK_MISC(this->priv->tabmenu_label), 0.0, 0);
378
498
 
379
 
        if (prefs.tab_order_ltr)
380
 
                tabnum = gtk_notebook_append_page_menu(GTK_NOTEBOOK(app->notebook), page,
381
 
                        hbox, this->tabmenu_label);
 
499
        if (file_prefs.tab_order_ltr)
 
500
                tabnum = gtk_notebook_append_page_menu(GTK_NOTEBOOK(main_widgets.notebook), page,
 
501
                        hbox, this->priv->tabmenu_label);
382
502
        else
383
 
                tabnum = gtk_notebook_insert_page_menu(GTK_NOTEBOOK(app->notebook), page,
384
 
                        hbox, this->tabmenu_label, 0);
 
503
                tabnum = gtk_notebook_insert_page_menu(GTK_NOTEBOOK(main_widgets.notebook), page,
 
504
                        hbox, this->priv->tabmenu_label, 0);
385
505
 
386
506
        tab_count_changed();
387
507
 
389
509
#if GTK_CHECK_VERSION(2, 10, 0)
390
510
        if (gtk_check_version(2, 10, 0) == NULL) /* null means version ok */
391
511
        {
392
 
                gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(app->notebook), page, TRUE);
 
512
                gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(main_widgets.notebook), page, TRUE);
393
513
        }
394
514
#endif
395
515
        g_free(title);
400
520
static void
401
521
notebook_tab_close_clicked_cb(GtkButton *button, gpointer user_data)
402
522
{
403
 
        gint cur_page = gtk_notebook_page_num(GTK_NOTEBOOK(app->notebook),
 
523
        gint cur_page = gtk_notebook_page_num(GTK_NOTEBOOK(main_widgets.notebook),
404
524
                GTK_WIDGET(user_data));
405
 
        document_remove(cur_page);
 
525
 
 
526
        document_remove_page(cur_page);
406
527
}
407
528
 
408
529
 
409
530
/* Always use this instead of gtk_notebook_remove_page(). */
410
531
void notebook_remove_page(gint page_num)
411
532
{
412
 
        gint curpage = gtk_notebook_get_current_page(GTK_NOTEBOOK(app->notebook));
 
533
        gint curpage = gtk_notebook_get_current_page(GTK_NOTEBOOK(main_widgets.notebook));
413
534
 
414
535
        /* Focus the next page, not the previous */
415
 
        if (curpage == page_num && prefs.tab_order_ltr)
 
536
        if (curpage == page_num && file_prefs.tab_order_ltr)
416
537
        {
417
 
                gtk_notebook_set_current_page(GTK_NOTEBOOK(app->notebook), curpage + 1);
 
538
                gtk_notebook_set_current_page(GTK_NOTEBOOK(main_widgets.notebook), curpage + 1);
418
539
        }
419
540
 
420
541
        /* now remove the page (so we don't temporarily switch to the previous page) */
421
 
        gtk_notebook_remove_page(GTK_NOTEBOOK(app->notebook), page_num);
 
542
        gtk_notebook_remove_page(GTK_NOTEBOOK(main_widgets.notebook), page_num);
422
543
 
423
544
        tab_count_changed();
424
545
}