1 /********************************************************************************
2 * *
3 * M u l t i p l e D o c u m e n t C h i l d W i n d o w *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1998,2005 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU Lesser General Public *
10 * License as published by the Free Software Foundation; either *
11 * version 2.1 of the License, or (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16 * Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public *
19 * License along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
21 *********************************************************************************
22 * $Id: FXMDIChild.cpp,v 1.88 2005/01/16 16:06:07 fox Exp $ *
23 ********************************************************************************/
24 #include "xincs.h"
25 #include "fxver.h"
26 #include "fxdefs.h"
27 #include "FXHash.h"
28 #include "FXThread.h"
29 #include "FXStream.h"
30 #include "FXString.h"
31 #include "FXSize.h"
32 #include "FXPoint.h"
33 #include "FXRectangle.h"
34 #include "FXRegistry.h"
35 #include "FXAccelTable.h"
36 #include "FXApp.h"
37 #include "FXDCWindow.h"
38 #include "FXFont.h"
39 #include "FXIcon.h"
40 #include "FXGIFIcon.h"
41 #include "FXWindow.h"
42 #include "FXFrame.h"
43 #include "FXLabel.h"
44 #include "FXButton.h"
45 #include "FXMenuButton.h"
46 #include "FXComposite.h"
47 #include "FXShell.h"
48 #include "FXPopup.h"
49 #include "FXMenuPane.h"
50 #include "FXScrollBar.h"
51 #include "FXScrollArea.h"
52 #include "FXMDIButton.h"
53 #include "FXMDIChild.h"
54 #include "FXMDIClient.h"
55
56
57 /*
58 Notes:
59 - Stacking order changes should be performed by MDIClient!
60 - Need options for MDI child decorations (close btn, window menu, min btn, max btn,
61 title etc).
62 - Iconified version should be fixed size, showing as much of title as feasible
63 (tail with ...'s)
64 - Initial icon placement on the bottom of the MDIClient somehow...
65 - Close v.s. delete messages are not consistent.
66 */
67
68 #define BORDERWIDTH 4 // MDI Child border width
69 #define HANDLESIZE 20 // Resize handle length
70 #define MINWIDTH 80 // Minimum width
71 #define MINHEIGHT 30 // Minimum height
72 #define TITLESPACE 120 // Width of title when minimized
73
74
75 using namespace FX;
76
77 /*******************************************************************************/
78
79 namespace FX {
80
81 // Map
82 FXDEFMAP(FXMDIChild) FXMDIChildMap[]={
83 FXMAPFUNC(SEL_PAINT,0,FXMDIChild::onPaint),
84 FXMAPFUNC(SEL_MOTION,0,FXMDIChild::onMotion),
85 FXMAPFUNC(SEL_FOCUSIN,0,FXMDIChild::onFocusIn),
86 FXMAPFUNC(SEL_FOCUSOUT,0,FXMDIChild::onFocusOut),
87 FXMAPFUNC(SEL_LEFTBUTTONPRESS,0,FXMDIChild::onLeftBtnPress),
88 FXMAPFUNC(SEL_LEFTBUTTONRELEASE,0,FXMDIChild::onLeftBtnRelease),
89 FXMAPFUNC(SEL_MIDDLEBUTTONPRESS,0,FXMDIChild::onMiddleBtnPress),
90 FXMAPFUNC(SEL_MIDDLEBUTTONRELEASE,0,FXMDIChild::onMiddleBtnRelease),
91 FXMAPFUNC(SEL_RIGHTBUTTONPRESS,0,FXMDIChild::onRightBtnPress),
92 FXMAPFUNC(SEL_RIGHTBUTTONRELEASE,0,FXMDIChild::onRightBtnRelease),
93 FXMAPFUNC(SEL_CLOSE,0,FXMDIChild::onCmdClose),
94 FXMAPFUNC(SEL_SELECTED,0,FXMDIChild::onSelected),
95 FXMAPFUNC(SEL_DESELECTED,0,FXMDIChild::onDeselected),
96 FXMAPFUNC(SEL_FOCUS_SELF,0,FXMDIChild::onFocusSelf),
97 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_CLOSE,FXMDIChild::onUpdClose),
98 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_MAXIMIZE,FXMDIChild::onUpdMaximize),
99 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_MINIMIZE,FXMDIChild::onUpdMinimize),
100 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_RESTORE,FXMDIChild::onUpdRestore),
101 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_WINDOW,FXMDIChild::onUpdWindow),
102 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_MENUCLOSE,FXMDIChild::onUpdMenuClose),
103 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_MENUMINIMIZE,FXMDIChild::onUpdMenuMinimize),
104 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_MENURESTORE,FXMDIChild::onUpdMenuRestore),
105 FXMAPFUNC(SEL_UPDATE,FXMDIChild::ID_MDI_MENUWINDOW,FXMDIChild::onUpdMenuWindow),
106 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_MDI_CLOSE,FXMDIChild::onCmdClose),
107 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_MDI_MAXIMIZE,FXMDIChild::onCmdMaximize),
108 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_MDI_MINIMIZE,FXMDIChild::onCmdMinimize),
109 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_MDI_RESTORE,FXMDIChild::onCmdRestore),
110 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_MDI_MENUCLOSE,FXMDIChild::onCmdClose),
111 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_MDI_MENUMINIMIZE,FXMDIChild::onCmdMinimize),
112 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_MDI_MENURESTORE,FXMDIChild::onCmdRestore),
113 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_SETSTRINGVALUE,FXMDIChild::onCmdSetStringValue),
114 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_GETSTRINGVALUE,FXMDIChild::onCmdGetStringValue),
115 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_SETICONVALUE,FXMDIChild::onCmdSetIconValue),
116 FXMAPFUNC(SEL_COMMAND,FXMDIChild::ID_GETICONVALUE,FXMDIChild::onCmdGetIconValue),
117 };
118
119
120 // Object implementation
FXIMPLEMENT(FXMDIChild,FXComposite,FXMDIChildMap,ARRAYNUMBER (FXMDIChildMap))121 FXIMPLEMENT(FXMDIChild,FXComposite,FXMDIChildMap,ARRAYNUMBER(FXMDIChildMap))
122
123
124 // Serialization
125 FXMDIChild::FXMDIChild(){
126 flags|=FLAG_ENABLED|FLAG_SHOWN;
127 windowbtn=(FXMenuButton*)-1L;
128 minimizebtn=(FXButton*)-1L;
129 restorebtn=(FXButton*)-1L;
130 maximizebtn=(FXButton*)-1L;
131 deletebtn=(FXButton*)-1L;
132 font=(FXFont*)-1L;
133 baseColor=0;
134 hiliteColor=0;
135 shadowColor=0;
136 borderColor=0;
137 titleColor=0;
138 titleBackColor=0;
139 iconPosX=0;
140 iconPosY=0;
141 iconWidth=0;
142 iconHeight=0;
143 normalPosX=0;
144 normalPosY=0;
145 normalWidth=0;
146 normalHeight=0;
147 spotx=0;
148 spoty=0;
149 xoff=0;
150 yoff=0;
151 newx=0;
152 newy=0;
153 neww=0;
154 newh=0;
155 mode=DRAG_NONE;
156 }
157
158
159 // Create MDI Child Window
FXMDIChild(FXMDIClient * p,const FXString & name,FXIcon * ic,FXPopup * pup,FXuint opts,FXint x,FXint y,FXint w,FXint h)160 FXMDIChild::FXMDIChild(FXMDIClient* p,const FXString& name,FXIcon* ic,FXPopup* pup,FXuint opts,FXint x,FXint y,FXint w,FXint h):
161 FXComposite(p,opts,x,y,w,h),title(name){
162 flags|=FLAG_ENABLED|FLAG_SHOWN;
163 windowbtn=new FXMDIWindowButton(this,pup,this,FXWindow::ID_MDI_WINDOW);
164 minimizebtn=new FXMDIMinimizeButton(this,this,FXWindow::ID_MDI_MINIMIZE,FRAME_RAISED);
165 restorebtn=new FXMDIRestoreButton(this,this,FXWindow::ID_MDI_RESTORE,FRAME_RAISED);
166 maximizebtn=new FXMDIMaximizeButton(this,this,FXWindow::ID_MDI_MAXIMIZE,FRAME_RAISED);
167 deletebtn=new FXMDIDeleteButton(this,this,FXWindow::ID_MDI_CLOSE,FRAME_RAISED);
168 windowbtn->setIcon(ic);
169 baseColor=getApp()->getBaseColor();
170 hiliteColor=getApp()->getHiliteColor();
171 shadowColor=getApp()->getShadowColor();
172 borderColor=getApp()->getBorderColor();
173 titleColor=getApp()->getSelforeColor();
174 titleBackColor=getApp()->getSelbackColor();
175 font=getApp()->getNormalFont();
176 iconPosX=xpos;
177 iconPosY=ypos;
178 iconWidth=width;
179 iconHeight=height;
180 normalPosX=xpos;
181 normalPosY=ypos;
182 normalWidth=width;
183 normalHeight=height;
184 if(options&(MDI_MAXIMIZED|MDI_MINIMIZED)){
185 normalWidth=p->getWidth()*2/3;
186 normalHeight=p->getHeight()*2/3;
187 if(normalWidth<8) normalWidth=200;
188 if(normalHeight<8) normalHeight=160;
189 }
190 spotx=0;
191 spoty=0;
192 xoff=0;
193 yoff=0;
194 newx=0;
195 newy=0;
196 neww=0;
197 newh=0;
198 mode=DRAG_NONE;
199 }
200
201
202 // Create window
create()203 void FXMDIChild::create(){
204 FXComposite::create();
205 font->create();
206 recalc();
207 }
208
209
210 // Detach window
detach()211 void FXMDIChild::detach(){
212 FXComposite::detach();
213 font->detach();
214 }
215
216
217 // Get content window (if any!)
contentWindow() const218 FXWindow *FXMDIChild::contentWindow() const {
219 return deletebtn->getNext();
220 }
221
222
223 // Get width
getDefaultWidth()224 FXint FXMDIChild::getDefaultWidth(){
225 FXint mw,bw;
226 mw=windowbtn->getDefaultWidth();
227 bw=deletebtn->getDefaultWidth();
228 return TITLESPACE+mw+3*bw+(BORDERWIDTH<<1)+2+4+4+6+2;
229 }
230
231
232 // Get height
getDefaultHeight()233 FXint FXMDIChild::getDefaultHeight(){
234 FXint fh,mh,bh;
235 fh=font->getFontHeight();
236 mh=windowbtn->getDefaultHeight();
237 bh=deletebtn->getDefaultHeight();
238 return FXMAX3(fh,mh,bh)+(BORDERWIDTH<<1)+2;
239 }
240
241
242 // Just tell server where the windows are!
layout()243 void FXMDIChild::layout(){
244 FXWindow *contents=contentWindow();
245 FXint th,fh,mw,mh,bw,bh,by,bx;
246 fh=font->getFontHeight();
247 mw=windowbtn->getDefaultWidth();
248 mh=windowbtn->getDefaultHeight();
249 bw=deletebtn->getDefaultWidth();
250 bh=deletebtn->getDefaultHeight();
251 th=FXMAX3(fh,mh,bh)+2;
252 bx=width-BORDERWIDTH-bw-2;
253 by=BORDERWIDTH+(th-bh)/2;
254 windowbtn->position(BORDERWIDTH+2,BORDERWIDTH+(th-mh)/2,mw,mh);
255 if(options&MDI_MAXIMIZED){
256 deletebtn->hide();
257 maximizebtn->hide();
258 minimizebtn->hide();
259 restorebtn->hide();
260 if(contents){
261 contents->position(0,0,width,height);
262 contents->raise();
263 contents->show();
264 }
265 }
266 else if(options&MDI_MINIMIZED){
267 deletebtn->position(bx,by,bw,bh); bx-=bw+3;
268 maximizebtn->position(bx,by,bw,bh); bx-=bw+3;
269 restorebtn->position(bx,by,bw,bh);
270 deletebtn->show();
271 maximizebtn->show();
272 minimizebtn->hide();
273 restorebtn->show();
274 if(contents){
275 contents->hide();
276 }
277 }
278 else{
279 deletebtn->position(bx,by,bw,bh); bx-=bw+3;
280 maximizebtn->position(bx,by,bw,bh); bx-=bw+3;
281 minimizebtn->position(bx,by,bw,bh);
282 deletebtn->show();
283 maximizebtn->show();
284 minimizebtn->show();
285 restorebtn->hide();
286 if(contents){
287 contents->position(BORDERWIDTH+2,BORDERWIDTH+2+th,width-(BORDERWIDTH<<1)-4,height-th-(BORDERWIDTH<<1)-4);
288 contents->show();
289 }
290 }
291 flags&=~FLAG_DIRTY;
292 }
293
294
295 // Maximize window
maximize(FXbool notify)296 FXbool FXMDIChild::maximize(FXbool notify){
297 if(!(options&MDI_MAXIMIZED)){
298 if(options&MDI_MINIMIZED){
299 iconPosX=xpos;
300 iconPosY=ypos;
301 iconWidth=width;
302 iconHeight=height;
303 }
304 else{
305 normalPosX=xpos;
306 normalPosY=ypos;
307 normalWidth=width;
308 normalHeight=height;
309 }
310 xpos=0;
311 ypos=0;
312 width=getParent()->getWidth();
313 height=getParent()->getHeight();
314 options|=MDI_MAXIMIZED;
315 options&=~MDI_MINIMIZED;
316 recalc();
317 if(notify && target){target->tryHandle(this,FXSEL(SEL_MAXIMIZE,message),NULL);}
318 }
319 return TRUE;
320 }
321
322
323 // Minimize window
minimize(FXbool notify)324 FXbool FXMDIChild::minimize(FXbool notify){
325 if(!(options&MDI_MINIMIZED)){
326 if(!(options&MDI_MAXIMIZED)){
327 normalPosX=xpos;
328 normalPosY=ypos;
329 normalWidth=width;
330 normalHeight=height;
331 }
332 xpos=iconPosX;
333 ypos=iconPosY;
334 width=getDefaultWidth();
335 height=getDefaultHeight();
336 options|=MDI_MINIMIZED;
337 options&=~MDI_MAXIMIZED;
338 recalc();
339 if(notify && target){target->tryHandle(this,FXSEL(SEL_MINIMIZE,message),NULL);}
340 }
341 return TRUE;
342 }
343
344
345 // Restore window
restore(FXbool notify)346 FXbool FXMDIChild::restore(FXbool notify){
347 if(options&(MDI_MINIMIZED|MDI_MAXIMIZED)){
348 if(options&MDI_MINIMIZED){
349 iconPosX=xpos;
350 iconPosY=ypos;
351 iconWidth=width;
352 iconHeight=height;
353 }
354 xpos=normalPosX;
355 ypos=normalPosY;
356 width=normalWidth;
357 height=normalHeight;
358 options&=~(MDI_MINIMIZED|MDI_MAXIMIZED);
359 recalc();
360 if(notify && target){target->tryHandle(this,FXSEL(SEL_RESTORE,message),NULL);}
361 }
362 return TRUE;
363 }
364
365
366 // Close MDI window, return TRUE if actually closed
close(FXbool notify)367 FXbool FXMDIChild::close(FXbool notify){
368 FXMDIClient *client=(FXMDIClient*)getParent();
369 FXMDIChild *alternative;
370
371 // See if OK to close
372 if(!notify || !target || !target->tryHandle(this,FXSEL(SEL_CLOSE,message),NULL)){
373
374 // Target will receive no further messages from us
375 setTarget(NULL);
376 setSelector(0);
377
378 // Try find another window to activate
379 alternative=(FXMDIChild*)(getNext()?getNext():getPrev());
380
381 // First make sure we're inactive
382 client->setActiveChild(alternative,notify);
383
384 // Self destruct
385 delete this;
386
387 // Was closed
388 return TRUE;
389 }
390 return FALSE;
391 }
392
393
394 // Is it maximized?
isMaximized() const395 FXbool FXMDIChild::isMaximized() const {
396 return (options&MDI_MAXIMIZED)!=0;
397 }
398
399
400 // Is it minimized
isMinimized() const401 FXbool FXMDIChild::isMinimized() const {
402 return (options&MDI_MINIMIZED)!=0;
403 }
404
405
406 // Move this window to the specified position in the parent's coordinates
move(FXint x,FXint y)407 void FXMDIChild::move(FXint x,FXint y){
408 FXComposite::move(x,y);
409 if(!(options&(MDI_MAXIMIZED|MDI_MINIMIZED))){
410 normalPosX=x;
411 normalPosY=y;
412 }
413 else if(options&MDI_MINIMIZED){
414 iconPosX=x;
415 iconPosY=y;
416 }
417 }
418
419
420 // Resize this window to the specified width and height
resize(FXint w,FXint h)421 void FXMDIChild::resize(FXint w,FXint h){
422 FXComposite::resize(w,h);
423 if(!(options&(MDI_MAXIMIZED|MDI_MINIMIZED))){
424 normalWidth=w;
425 normalHeight=h;
426 }
427 else if(options&MDI_MINIMIZED){
428 iconWidth=w;
429 iconHeight=h;
430 }
431 }
432
433
434 // Move and resize this window in the parent's coordinates
position(FXint x,FXint y,FXint w,FXint h)435 void FXMDIChild::position(FXint x,FXint y,FXint w,FXint h){
436 FXComposite::position(x,y,w,h);
437 if(!(options&(MDI_MAXIMIZED|MDI_MINIMIZED))){
438 normalPosX=x;
439 normalPosY=y;
440 normalWidth=w;
441 normalHeight=h;
442 }
443 else if(options&MDI_MINIMIZED){
444 iconPosX=x;
445 iconPosY=y;
446 iconWidth=w;
447 iconHeight=h;
448 }
449 }
450
451
452 // Into focus chain
setFocus()453 void FXMDIChild::setFocus(){
454 FXMDIClient *client=(FXMDIClient*)getParent();
455 client->setActiveChild(this,TRUE);
456 FXComposite::setFocus();
457 }
458
459
460 // If window can have focus
canFocus() const461 FXbool FXMDIChild::canFocus() const {
462 return TRUE;
463 }
464
465
466 // Change cursor based on location over window
changeCursor(FXint x,FXint y)467 void FXMDIChild::changeCursor(FXint x,FXint y){
468 switch(where(x,y)){
469 case DRAG_TOP:
470 case DRAG_BOTTOM:
471 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGH_CURSOR));
472 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGH_CURSOR));
473 break;
474 case DRAG_LEFT:
475 case DRAG_RIGHT:
476 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGV_CURSOR));
477 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGV_CURSOR));
478 break;
479 case DRAG_TOPLEFT:
480 case DRAG_BOTTOMRIGHT:
481 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGTL_CURSOR));
482 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGTL_CURSOR));
483 break;
484 case DRAG_TOPRIGHT:
485 case DRAG_BOTTOMLEFT:
486 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGTR_CURSOR));
487 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGTR_CURSOR));
488 break;
489 default:
490 setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
491 setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
492 break;
493 }
494 }
495
496
497 // Revert cursor to normal one
revertCursor()498 void FXMDIChild::revertCursor(){
499 setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
500 setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
501 }
502
503
504 // Draw rubberband box
drawRubberBox(FXint x,FXint y,FXint w,FXint h)505 void FXMDIChild::drawRubberBox(FXint x,FXint y,FXint w,FXint h){
506 if(BORDERWIDTH*2<w && BORDERWIDTH*2<h){
507 FXDCWindow dc(getParent());
508 dc.clipChildren(FALSE);
509 dc.setFunction(BLT_SRC_XOR_DST);
510 dc.setForeground(getParent()->getBackColor());
511 //dc.drawHashBox(xx,yy,w,h,BORDERWIDTH);
512 dc.setLineWidth(BORDERWIDTH);
513 dc.drawRectangle(x+BORDERWIDTH/2,y+BORDERWIDTH/2,w-BORDERWIDTH,h-BORDERWIDTH);
514 }
515 }
516
517
518 // Draw animation morphing from old to new rectangle
animateRectangles(FXint ox,FXint oy,FXint ow,FXint oh,FXint nx,FXint ny,FXint nw,FXint nh)519 void FXMDIChild::animateRectangles(FXint ox,FXint oy,FXint ow,FXint oh,FXint nx,FXint ny,FXint nw,FXint nh){
520 if(xid && getApp()->getAnimSpeed()){
521 FXDCWindow dc(getParent());
522 FXint bx,by,bw,bh,s,t;
523 dc.clipChildren(FALSE);
524 dc.setFunction(BLT_SRC_XOR_DST);
525 dc.setForeground(getParent()->getBackColor());
526 FXuint step=1+5000/getApp()->getAnimSpeed();
527 for(s=0,t=10000; s<=10000; s+=step,t-=step){
528 bx=(nx*s+ox*t)/10000;
529 by=(ny*s+oy*t)/10000;
530 bw=(nw*s+ow*t)/10000;
531 bh=(nh*s+oh*t)/10000;
532 if(BORDERWIDTH*2<bw && BORDERWIDTH*2<bh){
533 dc.drawHashBox(bx,by,bw,bh,BORDERWIDTH);
534 getApp()->flush(TRUE);
535 fxsleep(10000);
536 dc.drawHashBox(bx,by,bw,bh,BORDERWIDTH);
537 getApp()->flush(TRUE);
538 }
539 }
540 }
541 }
542
543
544 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)545 long FXMDIChild::onPaint(FXObject*,FXSelector,void* ptr){
546 FXEvent *ev=(FXEvent*)ptr;
547 FXint xx,yy,th,titlespace,letters,dots,dotspace;
548 FXint fh,mh,bh,bw,mw;
549
550 // If box is shown, hide it temporarily
551 if(mode&DRAG_INVERTED) drawRubberBox(newx,newy,neww,newh);
552
553 {
554 FXDCWindow dc(this,ev);
555
556 // Draw MDIChild background
557 dc.setForeground(baseColor);
558 dc.fillRectangle(ev->rect.x,ev->rect.y,ev->rect.w,ev->rect.h);
559
560 // Only draw stuff when not maximized
561 if(!(options&MDI_MAXIMIZED)){
562
563 // Compute sizes
564 fh=font->getFontHeight();
565 mw=windowbtn->getDefaultWidth();
566 mh=windowbtn->getDefaultHeight();
567 bw=deletebtn->getDefaultWidth();
568 bh=deletebtn->getDefaultHeight();
569 th=FXMAX3(fh,mh,bh)+2;
570
571 // Draw outer border
572 dc.setForeground(baseColor);
573 dc.fillRectangle(0,0,width-1,1);
574 dc.fillRectangle(0,0,1,height-2);
575 dc.setForeground(hiliteColor);
576 dc.fillRectangle(1,1,width-2,1);
577 dc.fillRectangle(1,1,1,height-2);
578 dc.setForeground(shadowColor);
579 dc.fillRectangle(1,height-2,width-1,1);
580 dc.fillRectangle(width-2,1,1,height-2);
581 dc.setForeground(borderColor);
582 dc.fillRectangle(0,height-1,width,1);
583 dc.fillRectangle(width-1,0,1,height);
584
585 // Draw title background
586 dc.setForeground(isActive() ? (hasFocus() ? titleBackColor : shadowColor) : backColor);
587 dc.fillRectangle(BORDERWIDTH,BORDERWIDTH,width-BORDERWIDTH*2,th);
588
589 // Draw title
590 if(!title.empty()){
591 xx=BORDERWIDTH+mw+2+4;
592 yy=BORDERWIDTH+font->getFontAscent()+(th-fh)/2;
593
594 // Compute space for title
595 titlespace=width-mw-3*bw-(BORDERWIDTH<<1)-2-4-4-6-2;
596
597 dots=0;
598 letters=title.length();
599
600 // Title too large for space
601 if(font->getTextWidth(title.text(),letters)>titlespace){
602 dotspace=titlespace-font->getTextWidth("...",3);
603 while(letters>0 && font->getTextWidth(title.text(),letters)>dotspace) letters--;
604 dots=3;
605 if(letters==0){
606 letters=1;
607 dots=0;
608 }
609 }
610
611 // Draw as much of the title as possible
612 dc.setForeground(isActive() ? titleColor : borderColor);
613 dc.setFont(font);
614 dc.drawText(xx,yy,title.text(),letters);
615 dc.drawText(xx+font->getTextWidth(title.text(),letters),yy,"...",dots);
616 }
617
618 // Draw inner border
619 if(!(options&MDI_MINIMIZED)){
620 dc.setForeground(shadowColor);
621 dc.fillRectangle(BORDERWIDTH,BORDERWIDTH+th,width-BORDERWIDTH*2-1,1);
622 dc.fillRectangle(BORDERWIDTH,BORDERWIDTH+th,1,height-th-BORDERWIDTH*2-1);
623 dc.setForeground(borderColor);
624 dc.fillRectangle(BORDERWIDTH+1,BORDERWIDTH+th+1,width-BORDERWIDTH*2-3,1);
625 dc.fillRectangle(BORDERWIDTH+1,BORDERWIDTH+th+1,1,height-th-BORDERWIDTH*2-3);
626 dc.setForeground(hiliteColor);
627 dc.fillRectangle(BORDERWIDTH,height-BORDERWIDTH-1,width-BORDERWIDTH*2,1);
628 dc.fillRectangle(width-BORDERWIDTH-1,BORDERWIDTH+th,1,height-th-BORDERWIDTH*2);
629 dc.setForeground(baseColor);
630 dc.fillRectangle(BORDERWIDTH+1,height-BORDERWIDTH-2,width-BORDERWIDTH*2-2,1);
631 dc.fillRectangle(width-BORDERWIDTH-2,BORDERWIDTH+th+1,1,height-th-BORDERWIDTH*2-2);
632 }
633 }
634 }
635
636 // Redraw the box over freshly painted window
637 if(mode&DRAG_INVERTED) drawRubberBox(newx,newy,neww,newh);
638
639 return 1;
640 }
641
642
643 // Find out where window was grabbed
where(FXint x,FXint y)644 FXuchar FXMDIChild::where(FXint x,FXint y){
645 FXuchar code=DRAG_NONE;
646 FXint fh,mh,bh,th;
647 fh=font->getFontHeight();
648 mh=windowbtn->getDefaultHeight();
649 bh=deletebtn->getDefaultHeight();
650 th=FXMAX3(fh,mh,bh)+2;
651 if(!isMinimized() && x<HANDLESIZE) code|=DRAG_LEFT;
652 if(!isMinimized() && width-HANDLESIZE<=x) code|=DRAG_RIGHT;
653 if(!isMinimized() && y<HANDLESIZE) code|=DRAG_TOP;
654 if(!isMinimized() && height-HANDLESIZE<=y) code|=DRAG_BOTTOM;
655 if(BORDERWIDTH<=x && x<=width-BORDERWIDTH && BORDERWIDTH<=y && y<BORDERWIDTH+th) code=DRAG_TITLE;
656 return code;
657 }
658
659
660 // Focus on widget itself
onFocusSelf(FXObject *,FXSelector,void * ptr)661 long FXMDIChild::onFocusSelf(FXObject*,FXSelector,void* ptr){
662 setFocus();
663 if(contentWindow()) contentWindow()->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
664 return 1;
665 // if(contentWindow() && contentWindow()->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
666 // setFocus();
667 // return 1; ///// FIXME See ScrollWindow /////
668 // FXWindow *child=contentWindow();
669 // return child && child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
670 }
671
672
673 // Gained focus
onFocusIn(FXObject * sender,FXSelector sel,void * ptr)674 long FXMDIChild::onFocusIn(FXObject* sender,FXSelector sel,void* ptr){
675 FXint fh,mh,bh,th;
676 FXComposite::onFocusIn(sender,sel,ptr);
677 fh=font->getFontHeight();
678 mh=windowbtn->getDefaultHeight();
679 bh=deletebtn->getDefaultHeight();
680 th=FXMAX3(fh,mh,bh)+2;
681 windowbtn->setBackColor(isActive() ? titleBackColor : backColor);
682 update(BORDERWIDTH,BORDERWIDTH,width-(BORDERWIDTH<<1),th);
683 return 1;
684 }
685
686
687 // Lost focus
onFocusOut(FXObject * sender,FXSelector sel,void * ptr)688 long FXMDIChild::onFocusOut(FXObject* sender,FXSelector sel,void* ptr){
689 FXint fh,mh,bh,th;
690 FXComposite::onFocusOut(sender,sel,ptr);
691 fh=font->getFontHeight();
692 mh=windowbtn->getDefaultHeight();
693 bh=deletebtn->getDefaultHeight();
694 th=FXMAX3(fh,mh,bh)+2;
695 windowbtn->setBackColor(isActive() ? shadowColor : backColor);
696 update(BORDERWIDTH,BORDERWIDTH,width-(BORDERWIDTH<<1),th);
697 return 1;
698 }
699
700
701 // Pressed LEFT button
onLeftBtnPress(FXObject *,FXSelector,void * ptr)702 long FXMDIChild::onLeftBtnPress(FXObject*,FXSelector,void* ptr){
703 register FXEvent *event=(FXEvent*)ptr;
704 flags&=~FLAG_TIP;
705 handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
706 if(isEnabled()){
707 grab();
708 if(target && target->tryHandle(this,FXSEL(SEL_LEFTBUTTONPRESS,message),ptr)) return 1;
709 if(event->click_count==1){
710 mode=where(event->win_x,event->win_y);
711 if(mode!=DRAG_NONE){
712 if(mode&(DRAG_TOP|DRAG_TITLE)) spoty=event->win_y;
713 else if(mode&DRAG_BOTTOM) spoty=event->win_y-height;
714 if(mode&(DRAG_LEFT|DRAG_TITLE)) spotx=event->win_x;
715 else if(mode&DRAG_RIGHT) spotx=event->win_x-width;
716 xoff=event->win_x+xpos-event->root_x;
717 yoff=event->win_y+ypos-event->root_y;
718 newx=xpos;
719 newy=ypos;
720 neww=width;
721 newh=height;
722 if(!(options&MDI_TRACKING)){
723 if(!(mode&DRAG_TITLE)){
724 drawRubberBox(newx,newy,neww,newh);
725 mode|=DRAG_INVERTED;
726 }
727 }
728 }
729 }
730 return 1;
731 }
732 return 0;
733 }
734
735
736 // Released LEFT button
onLeftBtnRelease(FXObject *,FXSelector,void * ptr)737 long FXMDIChild::onLeftBtnRelease(FXObject*,FXSelector,void* ptr){
738 register FXEvent *event=(FXEvent*)ptr;
739 if(isEnabled()){
740 ungrab();
741 if(target && target->tryHandle(this,FXSEL(SEL_LEFTBUTTONRELEASE,message),ptr)) return 1;
742 if(event->click_count==1){
743 if(mode!=DRAG_NONE){
744 if(!(options&MDI_TRACKING)){
745 if(mode&DRAG_INVERTED) drawRubberBox(newx,newy,neww,newh);
746 position(newx,newy,neww,newh);
747 }
748 mode=DRAG_NONE;
749 recalc();
750 }
751 }
752 else if(event->click_count==2){
753 if(options&MDI_MINIMIZED){
754 animateRectangles(xpos,ypos,width,height,normalPosX,normalPosY,normalWidth,normalHeight);
755 restore(TRUE);
756 }
757 else if(options&MDI_MAXIMIZED){
758 animateRectangles(xpos,ypos,width,height,normalPosX,normalPosY,normalWidth,normalHeight);
759 restore(TRUE);
760 }
761 else{
762 animateRectangles(xpos,ypos,width,height,0,0,getParent()->getWidth(),getParent()->getHeight());
763 maximize(TRUE);
764 }
765 }
766 return 1;
767 }
768 return 0;
769 }
770
771
772 // Moved
onMotion(FXObject *,FXSelector,void * ptr)773 long FXMDIChild::onMotion(FXObject*,FXSelector,void* ptr){
774 register FXEvent *event=(FXEvent*)ptr;
775 register FXint tmp,mousex,mousey;
776 register FXint oldx,oldy,oldw,oldh;
777 if(mode!=DRAG_NONE){
778
779 // Mouse in FXMDIClient's coordinates
780 mousex=event->root_x+xoff;
781 mousey=event->root_y+yoff;
782
783 // Keep inside FXMDIClient
784 if(mousex<0) mousex=0;
785 if(mousey<0) mousey=0;
786 if(mousex>=getParent()->getWidth()) mousex=getParent()->getWidth()-1;
787 if(mousey>=getParent()->getHeight()) mousey=getParent()->getHeight()-1;
788
789 // Remember old box
790 oldx=newx;
791 oldy=newy;
792 oldw=neww;
793 oldh=newh;
794
795 // Dragging title
796 if(mode&DRAG_TITLE){
797 if(!event->moved) return 1;
798 newy=mousey-spoty;
799 newx=mousex-spotx;
800 setDragCursor(getApp()->getDefaultCursor(DEF_MOVE_CURSOR));
801 }
802
803 // Dragging sides
804 else{
805
806 // Vertical
807 if(mode&DRAG_TOP){
808 tmp=newh+newy-mousey+spoty;
809 if(tmp>=MINHEIGHT){ newh=tmp; newy=mousey-spoty; }
810 }
811 else if(mode&DRAG_BOTTOM){
812 tmp=mousey-spoty-newy;
813 if(tmp>=MINHEIGHT){ newh=tmp; }
814 }
815
816 // Horizontal
817 if(mode&DRAG_LEFT){
818 tmp=neww+newx-mousex+spotx;
819 if(tmp>=MINWIDTH){ neww=tmp; newx=mousex-spotx; }
820 }
821 else if(mode&DRAG_RIGHT){
822 tmp=mousex-spotx-newx;
823 if(tmp>=MINWIDTH){ neww=tmp; }
824 }
825 }
826
827 // Move box
828 if(!(options&MDI_TRACKING)){
829 if(mode&DRAG_INVERTED) drawRubberBox(oldx,oldy,oldw,oldh);
830 drawRubberBox(newx,newy,neww,newh);
831 mode|=DRAG_INVERTED;
832 }
833 else{
834 position(newx,newy,neww,newh);
835 }
836 return 1;
837 }
838
839 // Othersize just change cursor based on location
840 changeCursor(event->win_x,event->win_y);
841 return 0;
842 }
843
844
845 // Pressed MIDDLE button
onMiddleBtnPress(FXObject *,FXSelector,void * ptr)846 long FXMDIChild::onMiddleBtnPress(FXObject*,FXSelector,void* ptr){
847 flags&=~FLAG_TIP;
848 handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
849 if(isEnabled()){
850 grab();
851 if(target && target->tryHandle(this,FXSEL(SEL_MIDDLEBUTTONPRESS,message),ptr)) return 1;
852 return 1;
853 }
854 return 0;
855 }
856
857
858 // Released MIDDLE button
onMiddleBtnRelease(FXObject *,FXSelector,void * ptr)859 long FXMDIChild::onMiddleBtnRelease(FXObject*,FXSelector,void* ptr){
860 if(isEnabled()){
861 ungrab();
862 if(target && target->tryHandle(this,FXSEL(SEL_MIDDLEBUTTONRELEASE,message),ptr)) return 1;
863 return 1;
864 }
865 return 0;
866 }
867
868
869 // Pressed RIGHT button
onRightBtnPress(FXObject *,FXSelector,void * ptr)870 long FXMDIChild::onRightBtnPress(FXObject*,FXSelector,void* ptr){
871 flags&=~FLAG_TIP;
872 if(isEnabled()){
873 grab();
874 if(target && target->tryHandle(this,FXSEL(SEL_RIGHTBUTTONPRESS,message),ptr)) return 1;
875 lower();
876 return 1;
877 }
878 return 0;
879 }
880
881
882 // Released RIGHT button
onRightBtnRelease(FXObject *,FXSelector,void * ptr)883 long FXMDIChild::onRightBtnRelease(FXObject*,FXSelector,void* ptr){
884 if(isEnabled()){
885 ungrab();
886 if(target && target->tryHandle(this,FXSEL(SEL_RIGHTBUTTONRELEASE,message),ptr)) return 1;
887 return 1;
888 }
889 return 0;
890 }
891
892
893 // Update value from a message
onCmdSetStringValue(FXObject *,FXSelector,void * ptr)894 long FXMDIChild::onCmdSetStringValue(FXObject*,FXSelector,void* ptr){
895 setTitle(*((FXString*)ptr));
896 return 1;
897 }
898
899
900 // Obtain value from text field
onCmdGetStringValue(FXObject *,FXSelector,void * ptr)901 long FXMDIChild::onCmdGetStringValue(FXObject*,FXSelector,void* ptr){
902 *((FXString*)ptr)=getTitle();
903 return 1;
904 }
905
906
907 // Update icon from a message
onCmdSetIconValue(FXObject *,FXSelector,void * ptr)908 long FXMDIChild::onCmdSetIconValue(FXObject*,FXSelector,void* ptr){
909 setIcon(*((FXIcon**)ptr));
910 return 1;
911 }
912
913
914 // Obtain icon from text field
onCmdGetIconValue(FXObject *,FXSelector,void * ptr)915 long FXMDIChild::onCmdGetIconValue(FXObject*,FXSelector,void* ptr){
916 *((FXIcon**)ptr)=getIcon();
917 return 1;
918 }
919
920
921 // Window was selected
onSelected(FXObject *,FXSelector,void * ptr)922 long FXMDIChild::onSelected(FXObject*,FXSelector,void* ptr){ // FIXME
923 if(!(flags&FLAG_ACTIVE)){
924 if(target) target->tryHandle(this,FXSEL(SEL_SELECTED,message),ptr);
925 windowbtn->setBackColor(hasFocus() ? titleBackColor : shadowColor);
926 flags|=FLAG_ACTIVE;
927 recalc();
928 update();
929 }
930 return 1;
931 }
932
933
934 // Window was deselected
onDeselected(FXObject *,FXSelector,void * ptr)935 long FXMDIChild::onDeselected(FXObject*,FXSelector,void* ptr){ // FIXME
936 if(flags&FLAG_ACTIVE){
937 if(target) target->tryHandle(this,FXSEL(SEL_DESELECTED,message),ptr);
938 windowbtn->setBackColor(backColor);
939 flags&=~FLAG_ACTIVE;
940 recalc();
941 update();
942 }
943 return 1;
944 }
945
946
947 /*******************************************************************************/
948
949
950 // Restore window command
onCmdRestore(FXObject *,FXSelector,void *)951 long FXMDIChild::onCmdRestore(FXObject*,FXSelector,void*){
952 animateRectangles(xpos,ypos,width,height,normalPosX,normalPosY,normalWidth,normalHeight);
953 restore(TRUE);
954 return 1;
955 }
956
957
958 // Update restore command
onUpdRestore(FXObject * sender,FXSelector,void *)959 long FXMDIChild::onUpdRestore(FXObject* sender,FXSelector,void*){
960 sender->handle(this,isMinimized()||isMaximized()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
961 return 1;
962 }
963
964
965 // Update MDI restore button on menu bar
onUpdMenuRestore(FXObject * sender,FXSelector,void *)966 long FXMDIChild::onUpdMenuRestore(FXObject* sender,FXSelector,void*){
967 if(isMaximized()){
968 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
969 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
970 }
971 else{
972 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
973 }
974 return 1;
975 }
976
977
978 // Maximize window command
onCmdMaximize(FXObject *,FXSelector,void *)979 long FXMDIChild::onCmdMaximize(FXObject*,FXSelector,void*){
980 animateRectangles(xpos,ypos,width,height,0,0,getParent()->getWidth(),getParent()->getHeight());
981 maximize(TRUE);
982 return 1;
983 }
984
985
986 // Update maximized command
onUpdMaximize(FXObject * sender,FXSelector,void *)987 long FXMDIChild::onUpdMaximize(FXObject* sender,FXSelector,void*){
988 sender->handle(this,isMaximized()?FXSEL(SEL_COMMAND,ID_DISABLE):FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
989 return 1;
990 }
991
992
993 // Minimize window command
onCmdMinimize(FXObject *,FXSelector,void *)994 long FXMDIChild::onCmdMinimize(FXObject*,FXSelector,void*){
995 animateRectangles(xpos,ypos,width,height,iconPosX,iconPosY,getDefaultWidth(),getDefaultHeight());
996 minimize(TRUE);
997 return 1;
998 }
999
1000
1001 // Update minimized command
onUpdMinimize(FXObject * sender,FXSelector,void *)1002 long FXMDIChild::onUpdMinimize(FXObject* sender,FXSelector,void*){
1003 sender->handle(this,isMinimized()?FXSEL(SEL_COMMAND,ID_DISABLE):FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1004 return 1;
1005 }
1006
1007
1008 // Update MDI minimized button on menu bar
onUpdMenuMinimize(FXObject * sender,FXSelector,void *)1009 long FXMDIChild::onUpdMenuMinimize(FXObject* sender,FXSelector,void*){
1010 if(isMaximized()){
1011 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
1012 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1013 }
1014 else{
1015 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
1016 }
1017 return 1;
1018 }
1019
1020
1021 // Close window after asking FXMDIChild's target; returns 1 if closed
onCmdClose(FXObject *,FXSelector,void *)1022 long FXMDIChild::onCmdClose(FXObject*,FXSelector,void*){
1023 return close(TRUE);
1024 }
1025
1026
1027 // Update close command
onUpdClose(FXObject * sender,FXSelector,void *)1028 long FXMDIChild::onUpdClose(FXObject* sender,FXSelector,void*){
1029 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1030 return 1;
1031 }
1032
1033
1034 // Update MDI close button on menu bar
onUpdMenuClose(FXObject * sender,FXSelector,void *)1035 long FXMDIChild::onUpdMenuClose(FXObject* sender,FXSelector,void*){
1036 if(isMaximized()){
1037 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1038 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
1039 }
1040 else{
1041 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
1042 }
1043 return 1;
1044 }
1045
1046
1047 // Update window menu button
onUpdWindow(FXObject * sender,FXSelector,void *)1048 long FXMDIChild::onUpdWindow(FXObject* sender,FXSelector,void*){
1049 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1050 return 1;
1051 }
1052
1053
1054 // Update MDI window menu button on menu bar
onUpdMenuWindow(FXObject * sender,FXSelector,void *)1055 long FXMDIChild::onUpdMenuWindow(FXObject* sender,FXSelector,void*){
1056 FXIcon *icon=getIcon();
1057 if(isMaximized()){
1058 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
1059 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1060 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETICONVALUE),(void*)&icon);
1061 }
1062 else{
1063 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
1064 }
1065 return 1;
1066 }
1067
1068
1069 // Set base color
setBaseColor(FXColor clr)1070 void FXMDIChild::setBaseColor(FXColor clr){
1071 if(baseColor!=clr){
1072 baseColor=clr;
1073 update();
1074 }
1075 }
1076
1077
1078 // Set highlight color
setHiliteColor(FXColor clr)1079 void FXMDIChild::setHiliteColor(FXColor clr){
1080 if(hiliteColor!=clr){
1081 hiliteColor=clr;
1082 update();
1083 }
1084 }
1085
1086
1087 // Set shadow color
setShadowColor(FXColor clr)1088 void FXMDIChild::setShadowColor(FXColor clr){
1089 if(shadowColor!=clr){
1090 shadowColor=clr;
1091 update();
1092 }
1093 }
1094
1095
1096 // Set border color
setBorderColor(FXColor clr)1097 void FXMDIChild::setBorderColor(FXColor clr){
1098 if(borderColor!=clr){
1099 borderColor=clr;
1100 update();
1101 }
1102 }
1103
1104
1105 // Set title color
setTitleColor(FXColor clr)1106 void FXMDIChild::setTitleColor(FXColor clr){
1107 if(titleColor!=clr){
1108 titleColor=clr;
1109 update();
1110 }
1111 }
1112
1113
1114 // Set title color
setTitleBackColor(FXColor clr)1115 void FXMDIChild::setTitleBackColor(FXColor clr){
1116 if(titleBackColor!=clr){
1117 titleBackColor=clr;
1118 update();
1119 }
1120 }
1121
1122
1123 // Set new window title
setTitle(const FXString & name)1124 void FXMDIChild::setTitle(const FXString& name){
1125 if(title!=name){
1126 title=name;
1127 update();
1128 }
1129 }
1130
1131
1132 // Delegate all other messages to child window
onDefault(FXObject * sender,FXSelector sel,void * ptr)1133 long FXMDIChild::onDefault(FXObject* sender,FXSelector sel,void* ptr){
1134
1135 // Try to handle in child
1136 if(contentWindow() && contentWindow()->tryHandle(sender,sel,ptr)) return 1;
1137
1138 // Bounce to target
1139 return target && target->tryHandle(sender,sel,ptr);
1140 }
1141
1142
1143 // Get icon used for the menu button
getIcon() const1144 FXIcon *FXMDIChild::getIcon() const {
1145 return windowbtn->getIcon();
1146 }
1147
1148
1149 // Change icon used for window menu button
setIcon(FXIcon * ic)1150 void FXMDIChild::setIcon(FXIcon* ic){
1151 windowbtn->setIcon(ic);
1152 }
1153
1154
1155 // Obtain window menu
getMenu() const1156 FXPopup* FXMDIChild::getMenu() const {
1157 return windowbtn->getMenu();
1158 }
1159
1160
1161 // Change window menu
setMenu(FXPopup * menu)1162 void FXMDIChild::setMenu(FXPopup* menu){
1163 windowbtn->setMenu(menu);
1164 }
1165
1166
1167 // Change the font
setFont(FXFont * fnt)1168 void FXMDIChild::setFont(FXFont *fnt){
1169 if(!fnt){ fxerror("%s::setFont: NULL font specified.\n",getClassName()); }
1170 if(font!=fnt){
1171 font=fnt;
1172 recalc();
1173 update();
1174 }
1175 }
1176
1177
1178 // Set tracking instead of just outline
setTracking(FXbool tracking)1179 void FXMDIChild::setTracking(FXbool tracking){
1180 if(tracking) options|=MDI_TRACKING; else options&=~MDI_TRACKING;
1181 }
1182
1183
1184 // Return true if tracking
getTracking() const1185 FXbool FXMDIChild::getTracking() const {
1186 return (options&MDI_TRACKING)!=0;
1187 }
1188
1189
1190 // Save object to stream
save(FXStream & store) const1191 void FXMDIChild::save(FXStream& store) const {
1192 FXComposite::save(store);
1193 store << title;
1194 store << windowbtn;
1195 store << minimizebtn;
1196 store << restorebtn;
1197 store << maximizebtn;
1198 store << deletebtn;
1199 store << font;
1200 store << baseColor;
1201 store << hiliteColor;
1202 store << shadowColor;
1203 store << borderColor;
1204 store << titleColor;
1205 store << titleBackColor;
1206 store << iconPosX;
1207 store << iconPosY;
1208 store << iconWidth;
1209 store << iconHeight;
1210 store << normalPosX;
1211 store << normalPosY;
1212 store << normalWidth;
1213 store << normalHeight;
1214 }
1215
1216
1217 // Load object from stream
load(FXStream & store)1218 void FXMDIChild::load(FXStream& store){
1219 FXComposite::load(store);
1220 store >> title;
1221 store >> windowbtn;
1222 store >> minimizebtn;
1223 store >> restorebtn;
1224 store >> maximizebtn;
1225 store >> deletebtn;
1226 store >> font;
1227 store >> baseColor;
1228 store >> hiliteColor;
1229 store >> shadowColor;
1230 store >> borderColor;
1231 store >> titleColor;
1232 store >> titleBackColor;
1233 store >> iconPosX;
1234 store >> iconPosY;
1235 store >> iconWidth;
1236 store >> iconHeight;
1237 store >> normalPosX;
1238 store >> normalPosY;
1239 store >> normalWidth;
1240 store >> normalHeight;
1241 }
1242
1243
1244 // Destruct thrashes the pointers
~FXMDIChild()1245 FXMDIChild::~FXMDIChild(){
1246 if(((FXMDIClient*)getParent())->active==this) ((FXMDIClient*)getParent())->active=NULL;
1247 windowbtn=(FXMenuButton*)-1L;
1248 minimizebtn=(FXButton*)-1L;
1249 restorebtn=(FXButton*)-1L;
1250 maximizebtn=(FXButton*)-1L;
1251 deletebtn=(FXButton*)-1L;
1252 font=(FXFont*)-1L;
1253 }
1254
1255 }
1256