2 * (c) 2010 Cyrill Gorcunov, gorcunov@gmail.com
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 2 of the License, or (at
7 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * 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.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28 #include <sys/param.h>
29 #include <sys/types.h>
38 #include "sourceview.h"
40 #include "backend-proto.h"
42 #define NB_PAGE_LOCKED_IMG GTK_STOCK_NO
43 #define NB_PAGE_UNLOCKED_IMG GTK_STOCK_YES
45 #define NB_CLOSE_PAGE_RC_NAME "nb_page_close-button"
46 static const char nb_page_close_rc
[] =
47 "style \"nb_page_close-style\"\n"
49 " GtkWidget::focus-padding = 0\n"
50 " GtkWidget::focus-line-width = 0\n"
54 "widget \"*.nb_page_close-button\" style \"nb_page_close-style\"";
56 #define NB_LOCK_PAGE_RC_NAME "nb_page_lock-button"
57 static const char nb_page_lock_rc
[] =
58 "style \"nb_page_lock-style\"\n"
60 " GtkWidget::focus-padding = 0\n"
61 " GtkWidget::focus-line-width = 0\n"
65 "widget \"*.nb_page_lock-button\" style \"nb_page_lock-style\"";
67 void notebook_init(void)
69 gtk_rc_parse_string(nb_page_close_rc
);
70 gtk_rc_parse_string(nb_page_lock_rc
);
73 void notebook_fini(void)
75 /* FIXME: Something there? */
78 static void notebook_delete_title(struct notebook_title
*title
)
80 gtk_widget_destroy(title
->label
);
81 gtk_widget_destroy(title
->lock_image
);
82 gtk_widget_destroy(title
->lock_button
);
83 gtk_widget_destroy(title
->close_image
);
84 gtk_widget_destroy(title
->close_button
);
86 memset(title
, 0, sizeof(*title
));
89 static void notebook_delete_page(struct notebook_page
*page
)
91 GtkNotebook
*nb
= GTK_NOTEBOOK(page
->notebook
->me
);
95 notebook_delete_title(&page
->title
);
97 /* child widget (text view and friends) */
100 * NOTE: If child widget embedded into notebook
101 * deletes itself we should not call gtk_notebook_remove_page
102 * the GTK will delete the page by self
104 if (page
->child_delete_hook
) {
105 page
->child_delete_hook(page
->child
, page
->private);
107 pos
= gtk_notebook_page_num(nb
, page
->child
);
108 if (pos
!= NB_ENOPAGE
)
109 gtk_notebook_remove_page(GTK_NOTEBOOK(page
->notebook
->me
), pos
);
113 list_del(&page
->siblings
);
117 static void cb_page_switched(GtkNotebook
*nb
, GtkWidget
*pg
,
118 guint page_num
, gpointer user_data
)
120 struct notebook
*notebook
= (struct notebook
*)user_data
;
121 struct notebook_page
*page
;
124 list_for_each_entry(page
, ¬ebook
->pages
, siblings
) {
125 num
= gtk_notebook_page_num(GTK_NOTEBOOK(notebook
->me
), page
->child
);
126 if (num
== page_num
) {
127 if (page
->page_changed_hook
)
128 page
->page_changed_hook(page
);
135 struct notebook
*notebook_create(void)
137 struct notebook
*notebook
= xzalloc(sizeof(*notebook
));
139 notebook
->me
= GTK_WIDGET(gtk_notebook_new());
140 INIT_LIST_HEAD(¬ebook
->pages
);
142 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook
->me
), TRUE
);
145 g_signal_connect(G_OBJECT(notebook
->me
), "switch-page",
146 G_CALLBACK(cb_page_switched
), (gpointer
)notebook
);
151 void notebook_delete(struct notebook
*notebook
)
156 if (!list_empty(¬ebook
->pages
)) {
157 struct notebook_page
*page
, *n
;
158 list_for_each_entry_safe(page
, n
, ¬ebook
->pages
, siblings
)
159 notebook_delete_page(page
);
162 gtk_widget_destroy(notebook
->me
);
166 static void cb_lock_page(GtkButton
*widget
, gpointer data
)
168 struct notebook_page
*page
= data
;
169 GtkImage
*image
= GTK_IMAGE(page
->title
.lock_image
);
171 gtk_image_clear(image
);
173 if (page
->status
& NB_STATUS_LOCKED
) {
174 gtk_image_set_from_stock(image
, NB_PAGE_UNLOCKED_IMG
, GTK_ICON_SIZE_MENU
);
175 page
->status
&= ~NB_STATUS_LOCKED
;
177 gtk_image_set_from_stock(image
, GTK_STOCK_NO
, GTK_ICON_SIZE_MENU
);
178 page
->status
|= NB_STATUS_LOCKED
;
181 gtk_widget_show_all(GTK_WIDGET(image
));
184 static void cb_close_page(GtkButton
*widget
, gpointer data
)
186 struct notebook_page
*notebook_page
= data
;
187 if (!(notebook_page
->status
& NB_STATUS_LOCKED
))
188 notebook_delete_page((struct notebook_page
*)data
);
191 /* create new empty page */
192 struct notebook_page
*notebook_create_page(struct notebook
*notebook
, char *title
, int title_nchars
, int status
)
194 struct notebook_page
*page
;
196 page
= xzalloc(sizeof(*page
));
197 page
->status
= status
;
198 page
->title
.container
= gtk_hbox_new(FALSE
, 3);
199 page
->title
.label
= gtk_label_new(title
);
200 page
->title
.close_button
= gtk_button_new();
201 page
->title
.lock_button
= gtk_button_new();
202 page
->title
.close_image
= gtk_image_new_from_stock(GTK_STOCK_CLOSE
, GTK_ICON_SIZE_MENU
);
203 page
->title
.lock_image
= gtk_image_new_from_stock(NB_PAGE_UNLOCKED_IMG
, GTK_ICON_SIZE_MENU
);
205 gtk_label_set_max_width_chars(GTK_LABEL(page
->title
.label
), title_nchars
);
207 gtk_widget_set_name(page
->title
.close_button
, NB_CLOSE_PAGE_RC_NAME
);
208 gtk_widget_set_name(page
->title
.close_button
, NB_LOCK_PAGE_RC_NAME
);
210 gtk_button_set_relief(GTK_BUTTON(page
->title
.close_button
), GTK_RELIEF_NONE
);
211 gtk_button_set_relief(GTK_BUTTON(page
->title
.lock_button
), GTK_RELIEF_NONE
);
213 gtk_box_pack_start(GTK_BOX(page
->title
.container
), page
->title
.lock_button
, TRUE
, TRUE
, 0);
214 gtk_box_pack_start(GTK_BOX(page
->title
.container
), page
->title
.label
, TRUE
, TRUE
, 0);
215 gtk_box_pack_start(GTK_BOX(page
->title
.container
), page
->title
.close_button
, FALSE
, FALSE
, 0);
217 gtk_container_add(GTK_CONTAINER(page
->title
.lock_button
), page
->title
.lock_image
);
218 gtk_container_add(GTK_CONTAINER(page
->title
.close_button
), page
->title
.close_image
);
220 /* buttons signals */
221 g_signal_connect(page
->title
.lock_button
, "clicked", G_CALLBACK(cb_lock_page
), page
);
222 g_signal_connect(page
->title
.close_button
, "clicked", G_CALLBACK(cb_close_page
), page
);
224 gtk_widget_show_all(page
->title
.container
);
226 /* link to notebook */
227 page
->notebook
= notebook
;
228 list_add(&page
->siblings
, ¬ebook
->pages
);
233 void notebook_page_child_attach(struct notebook_page
*page
, GtkWidget
*widget
, void *private,
234 void (*page_changed_hook
)(struct notebook_page
*page
),
235 void (*child_delete_hook
)(GtkWidget
*child
, void *private))
237 page
->child
= widget
;
238 page
->page_changed_hook
= page_changed_hook
;
239 page
->child_delete_hook
= child_delete_hook
;
240 page
->private = private;
242 gtk_notebook_append_page(GTK_NOTEBOOK(page
->notebook
->me
), widget
, page
->title
.container
);
243 gtk_notebook_set_tab_reorderable(GTK_NOTEBOOK(page
->notebook
->me
), widget
, TRUE
);
246 void notebook_page_child_dettach(struct notebook_page
*page
)
249 page
->child_delete_hook
= NULL
;
250 page
->private = NULL
;
253 void notebook_activate_page(struct notebook
*notebook
, struct notebook_page
*page
)
256 gtk_widget_show(page
->child
);
257 num
= gtk_notebook_page_num(GTK_NOTEBOOK(notebook
->me
), page
->child
);
258 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook
->me
), num
);
261 struct notebook_page
*notebook_page_find(struct notebook
*notebook
, GtkWidget
*child
)
263 struct notebook_page
*page
;
265 list_for_each_entry(page
, ¬ebook
->pages
, siblings
) {
266 if (page
->child
== child
)