1 /*
2
3 eboard - chess client
4 http://www.bergo.eng.br/eboard
5 https://github.com/fbergo/eboard
6 Copyright (C) 2000-2016 Felipe Bergo
7 fbergo/at/gmail/dot/com
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 */
24
25 #include <iostream>
26 #include "eboard.h"
27 #include "global.h"
28 #include "notebook.h"
29
30 #include "xpm/dead.xpm"
31 #include "xpm/trash2.xpm"
32
page_trash(GtkWidget * w,gpointer data)33 void page_trash(GtkWidget *w, gpointer data) {
34 Page *p;
35 p=(Page *) data;
36 global.removeRemovablePage(p->number);
37 }
38
Page()39 Page::Page() {
40 global.debug("Page","Page","1");
41 number=0;
42 content=0;
43 title[0]=0;
44 naughty=false;
45 level=IM_ZERO;
46 label=gtk_label_new("<none>");
47 gshow(label);
48 }
49
Page(int _number,GtkWidget * _content,char * _title,bool _removable)50 Page::Page(int _number,GtkWidget *_content, char *_title, bool _removable) {
51
52 GtkWidget *b,*p;
53
54 global.debug("Page","Page","2");
55 number=_number;
56 content=_content;
57 level=IM_ZERO;
58 naughty=false;
59 removable=_removable;
60
61 g_strlcpy(title,_title,256);
62
63 if (removable) {
64
65 labelframe=gtk_hbox_new(FALSE,1);
66
67 Notebook::ensurePixmaps();
68 b=gtk_button_new();
69 gtk_button_set_relief(GTK_BUTTON(b), GTK_RELIEF_HALF);
70 p=gtk_pixmap_new(Notebook::trashface, Notebook::trashmask);
71 gtk_container_add(GTK_CONTAINER(b), p);
72 gtk_box_pack_start(GTK_BOX(labelframe), b, FALSE, FALSE, 0);
73
74 label=gtk_label_new(title);
75 gtk_box_pack_start(GTK_BOX(labelframe), label, FALSE, TRUE, 1);
76
77 Gtk::show(p,b,label,labelframe,NULL);
78
79 gtk_signal_connect(GTK_OBJECT(b),"clicked",
80 GTK_SIGNAL_FUNC(page_trash), (gpointer) this);
81
82 } else {
83
84 label=gtk_label_new(title);
85 gshow(label);
86 labelframe=label;
87
88 }
89 }
90
operator ==(int n)91 int Page::operator==(int n) {
92 return(n==number);
93 }
94
under(Importance imp)95 int Page::under(Importance imp) {
96 return(level < imp);
97 }
98
above(Importance imp)99 int Page::above(Importance imp) {
100 return(level > imp);
101 }
102
setLevel(Importance imp)103 void Page::setLevel(Importance imp) {
104 level=imp;
105 }
106
setTitle(char * _title)107 void Page::setTitle(char *_title) {
108 g_strlcpy(title,_title,256);
109 gtk_label_set_text(GTK_LABEL(label),title);
110 gtk_widget_queue_resize(label);
111 }
112
getTitle()113 char * Page::getTitle() {
114 return(title);
115 }
116
renumber(int newid)117 void Page::renumber(int newid) {
118 char z[258];
119 number=newid;
120 snprintf(z,258,"{%s}",title);
121 setTitle(z);
122 }
123
dump()124 void Page::dump() {
125 cerr.setf(ios::hex,ios::basefield);
126 cerr.setf(ios::showbase);
127 cerr << "[page " << ((uint64_t)this) << "] ";
128 cerr.setf(ios::dec,ios::basefield);
129 cerr << "pageid=" << number << " ";
130 cerr << "title=" << title << " ";
131 cerr << "level=" << ((int)level) << endl;
132 }
133
134 GdkPixmap * Notebook::trashface=0;
135 GdkBitmap * Notebook::trashmask=0;
136 GtkWidget * Notebook::swidget=0;
137
ensurePixmaps()138 void Notebook::ensurePixmaps() {
139 GtkStyle *style;
140
141 if (swidget==0) return;
142
143 if (trashface==0) {
144 style=gtk_widget_get_style(swidget);
145 trashface = gdk_pixmap_create_from_xpm_d (swidget->window, &trashmask,
146 &style->bg[GTK_STATE_NORMAL],
147 (gchar **) trash2_xpm);
148 }
149 }
150
Notebook()151 Notebook::Notebook() {
152 global.debug("Notebook","Notebook");
153 pcl=0;
154 widget=gtk_notebook_new();
155 swidget=widget;
156 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(widget),GTK_POS_RIGHT);
157 gtk_notebook_set_scrollable(GTK_NOTEBOOK(widget),TRUE);
158 gtk_signal_connect(GTK_OBJECT(widget),"switch_page",
159 GTK_SIGNAL_FUNC(notebook_switch_page),
160 (gpointer)this);
161 }
162
addPage(GtkWidget * what,char * title,int id,bool removable)163 void Notebook::addPage(GtkWidget *what,char *title,int id,bool removable) {
164 Page *pg;
165 global.debug("Notebook","addPage",title);
166 pg=new Page(id,what,title,removable);
167 pages.push_back(pg);
168 gtk_notebook_append_page(GTK_NOTEBOOK(widget),what,pg->labelframe);
169
170 /* to test graphics only, adds dead.xpm to console tab
171 if (pages.size() == 2)
172 addBombToTab(pg);
173 */
174 }
175
removePage(int id)176 void Notebook::removePage(int id) {
177 vector<Page *>::iterator pi;
178 int i;
179 global.debug("Notebook","removePage");
180 for(i=0,pi=pages.begin();pi!=pages.end();pi++,i++)
181 if ( (*(*pi)) == id ) {
182 gtk_notebook_remove_page(GTK_NOTEBOOK(widget),i);
183 delete(*pi);
184 pages.erase(pi);
185 return;
186 }
187 }
188
getCurrentPage()189 unsigned int Notebook::getCurrentPage() {
190 return((unsigned int)gtk_notebook_get_current_page(GTK_NOTEBOOK(widget)));
191 }
192
getCurrentPageId()193 int Notebook::getCurrentPageId() {
194 unsigned int i;
195 i=getCurrentPage();
196 if (i >= pages.size())
197 return 0;
198 return( pages[i]->number );
199 }
200
setTabColor(int pageid,int color,Importance imp)201 void Notebook::setTabColor(int pageid,int color,Importance imp) {
202 vector<Page *>::iterator pi;
203 int i;
204 global.debug("Notebook","setTabColor","1");
205 for(i=0,pi=pages.begin();pi!=pages.end();pi++,i++)
206 if ( (*(*pi)) == pageid ) {
207 setTabColor(i,color,0,imp);
208 return;
209 }
210 }
211
setTabColor(int page_num,int color,int poly,Importance imp)212 void Notebook::setTabColor(int page_num,int color,int poly,
213 Importance imp) {
214 vector<Page *>::iterator pi;
215 GdkColor nc;
216 GtkStyle *style;
217 int i;
218 i=page_num;
219
220 global.debug("Notebook","setTabColor","2");
221 for(pi=pages.begin();i;pi++,i--) ;
222
223 if ((*pi)->above(imp))
224 return;
225
226 if (imp==IM_RESET) imp=IM_ZERO;
227 (*pi)->setLevel(imp);
228
229 nc.red=((color>>16)<<8);
230 nc.green=(color&0x00ff00);
231 nc.blue=((color&0xff)<<8);
232 style=gtk_style_copy( gtk_widget_get_style((*pi)->label) );
233
234 for(i=0;i<5;i++)
235 style->fg[i]=nc;
236
237 gtk_widget_set_style( (*pi)->label, style );
238 gtk_widget_ensure_style( (*pi)->label );
239 gtk_widget_queue_draw( (*pi)->label );
240
241 gtk_style_unref(style); // tomv, leak
242 }
243
goToPageId(int id)244 void Notebook::goToPageId(int id) {
245 vector<Page *>::iterator pi;
246 int i;
247 for(i=0,pi=pages.begin();pi!=pages.end();pi++,i++)
248 if ( (*(*pi)) == id ) {
249 gtk_notebook_set_page(GTK_NOTEBOOK(widget),i);
250 return;
251 }
252 }
253
setTabPosition(GtkPositionType pos)254 void Notebook::setTabPosition(GtkPositionType pos) {
255 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(widget),pos);
256 }
257
dump()258 void Notebook::dump() {
259 vector<Page *>::iterator pi;
260 for(pi=pages.begin();pi!=pages.end();pi++)
261 (*pi)->dump();
262 }
263
goToNext()264 void Notebook::goToNext() {
265 gtk_notebook_next_page(GTK_NOTEBOOK(widget));
266 }
267
goToPrevious()268 void Notebook::goToPrevious() {
269 gtk_notebook_prev_page(GTK_NOTEBOOK(widget));
270 }
271
renumberPage(int oldid,int newid)272 void Notebook::renumberPage(int oldid,int newid) {
273 vector<Page *>::iterator i;
274 for(i=pages.begin();i!=pages.end();i++)
275 if ( (*(*i)) == oldid )
276 (*i)->renumber(newid);
277 }
278
setListener(PaneChangeListener * listener)279 void Notebook::setListener(PaneChangeListener *listener) {
280 pcl=listener;
281 }
282
setNaughty(int pageid,bool val)283 void Notebook::setNaughty(int pageid, bool val) {
284 vector<Page *>::iterator i;
285 for(i=pages.begin();i!=pages.end();i++)
286 if ( (*(*i)) == pageid ) {
287
288 if ( (val)&&(! (*i)->naughty) )
289 addBombToTab(*i);
290 (*i)->naughty=val;
291
292 }
293 }
294
getNaughty(vector<int> & evil_ids)295 void Notebook::getNaughty(vector<int> &evil_ids) {
296 vector<Page *>::iterator i;
297 evil_ids.clear();
298 for(i=pages.begin();i!=pages.end();i++)
299 if ( (*i)->naughty )
300 evil_ids.push_back( (*i)->number );
301 }
302
isNaughty(int pageid)303 bool Notebook::isNaughty(int pageid) {
304 vector<Page *>::iterator i;
305 for(i=pages.begin();i!=pages.end();i++)
306 if ( (*i)->number == pageid )
307 if ((*i)->naughty)
308 return true;
309 return false;
310 }
311
hasNaughty()312 bool Notebook::hasNaughty() {
313 vector<Page *>::iterator i;
314 for(i=pages.begin();i!=pages.end();i++)
315 if ( (*i)->naughty )
316 return true;
317 return false;
318 }
319
320 // SOMEONE SET UP US THE BOMB!
addBombToTab(Page * pg)321 void Notebook::addBombToTab(Page *pg) {
322 GtkWidget *hb,*label,*pm;
323 GdkPixmap *d;
324 GdkBitmap *b;
325 GtkStyle *style;
326
327 style=gtk_widget_get_default_style();
328
329 d = gdk_pixmap_create_from_xpm_d (widget->window, &b,
330 &style->bg[GTK_STATE_NORMAL],
331 (gchar **) dead_xpm);
332 pm=gtk_pixmap_new(d,b);
333
334 label=gtk_label_new(pg->getTitle());
335 hb=gtk_hbox_new(FALSE,2);
336
337 gtk_box_pack_start(GTK_BOX(hb),label,FALSE,FALSE,4);
338 gtk_box_pack_start(GTK_BOX(hb),pm,FALSE,FALSE,4);
339
340 Gtk::show(label,pm,hb,NULL);
341
342 pg->label=label;
343 gtk_notebook_set_tab_label(GTK_NOTEBOOK(widget),pg->content,hb);
344 }
345
pretendPaneChanged()346 void Notebook::pretendPaneChanged() {
347 if (pcl)
348 pcl->paneChanged( getCurrentPage(), getCurrentPageId() );
349 }
350
351 void
notebook_switch_page(GtkNotebook * notebook,GtkNotebookPage * page,gint page_num,gpointer data)352 notebook_switch_page(GtkNotebook *notebook,
353 GtkNotebookPage *page,
354 gint page_num,
355 gpointer data) {
356 Notebook *me;
357 unsigned int pg = (unsigned int) page_num;
358 me=(Notebook *)data;
359 me->setTabColor(pg,0,0,IM_RESET);
360 if ( (me->pcl) && (me->pages.size() > pg) )
361 me->pcl->paneChanged(pg, me->pages[pg]->number);
362 }
363
364 // ================================================================
365
NotebookInsider()366 NotebookInsider::NotebookInsider() {
367 mynotebook=0;
368 pgid=0;
369 }
370
setNotebook(Notebook * nb,int pageid)371 void NotebookInsider::setNotebook(Notebook *nb,int pageid) {
372 pgid=pageid;
373 mynotebook=nb;
374 }
375
contentUpdated()376 void NotebookInsider::contentUpdated() {
377 int color=0xff0000;
378 Importance maxi=IM_NORMAL;
379 global.debug("NotebookInsider","contentUpdated");
380 if (!impstack.empty()) {
381 maxi=IM_IGNORE;
382 while(!impstack.empty()) {
383 if (impstack.top() > maxi) maxi=impstack.top();
384 impstack.pop();
385 }
386 switch(maxi) {
387 case IM_IGNORE:
388 return;
389 case IM_NORMAL:
390 color=0xff0000;
391 break;
392 case IM_PERSONAL:
393 color=0x0000ff;
394 break;
395 default:
396 color=0x00ff00; /* will never happen */
397 break;
398 }
399 }
400 if (!mynotebook)
401 return;
402 if (mynotebook->getCurrentPageId() != pgid)
403 mynotebook->setTabColor(pgid,color,maxi);
404 }
405
pop()406 void NotebookInsider::pop() {
407 global.debug("NotebookInsider","pop");
408 if (!mynotebook)
409 return;
410 mynotebook->goToPageId(pgid);
411 }
412
pushLevel(Importance imp)413 void NotebookInsider::pushLevel(Importance imp) {
414 impstack.push(imp);
415 }
416
getPageId()417 int NotebookInsider::getPageId() {
418 return(pgid);
419 }
420