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,2006 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 4937 2019-03-10 19:59:30Z arthurcnorman $ *
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 bool FXMDIChild::canFocus() const { return true; }
462
463
464 // Change cursor based on location over window
changeCursor(FXint x,FXint y)465 void FXMDIChild::changeCursor(FXint x,FXint y){
466 switch(where(x,y)){
467 case DRAG_TOP:
468 case DRAG_BOTTOM:
469 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGH_CURSOR));
470 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGH_CURSOR));
471 break;
472 case DRAG_LEFT:
473 case DRAG_RIGHT:
474 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGV_CURSOR));
475 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGV_CURSOR));
476 break;
477 case DRAG_TOPLEFT:
478 case DRAG_BOTTOMRIGHT:
479 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGTL_CURSOR));
480 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGTL_CURSOR));
481 break;
482 case DRAG_TOPRIGHT:
483 case DRAG_BOTTOMLEFT:
484 setDefaultCursor(getApp()->getDefaultCursor(DEF_DRAGTR_CURSOR));
485 setDragCursor(getApp()->getDefaultCursor(DEF_DRAGTR_CURSOR));
486 break;
487 default:
488 setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
489 setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
490 break;
491 }
492 }
493
494
495 // Revert cursor to normal one
revertCursor()496 void FXMDIChild::revertCursor(){
497 setDefaultCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
498 setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR));
499 }
500
501
502 // Draw rubberband box
drawRubberBox(FXint x,FXint y,FXint w,FXint h)503 void FXMDIChild::drawRubberBox(FXint x,FXint y,FXint w,FXint h){
504 if(BORDERWIDTH*2<w && BORDERWIDTH*2<h){
505 FXDCWindow dc(getParent());
506 dc.clipChildren(FALSE);
507 dc.setFunction(BLT_SRC_XOR_DST);
508 dc.setForeground(getParent()->getBackColor());
509 //dc.drawHashBox(xx,yy,w,h,BORDERWIDTH);
510 dc.setLineWidth(BORDERWIDTH);
511 dc.drawRectangle(x+BORDERWIDTH/2,y+BORDERWIDTH/2,w-BORDERWIDTH,h-BORDERWIDTH);
512 }
513 }
514
515
516 // 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)517 void FXMDIChild::animateRectangles(FXint ox,FXint oy,FXint ow,FXint oh,FXint nx,FXint ny,FXint nw,FXint nh){
518 FXlong pause=getApp()->getAnimSpeed()*1000000L;
519 if(xid && pause){
520 FXDCWindow dc(getParent());
521 FXint bx,by,bw,bh,s,t;
522 dc.clipChildren(false);
523 dc.setFunction(BLT_SRC_XOR_DST);
524 dc.setForeground(getParent()->getBackColor());
525 FXuint step=500;
526 for(s=0,t=10000; s<=10000; s+=step,t-=step){
527 bx=(nx*s+ox*t)/10000;
528 by=(ny*s+oy*t)/10000;
529 bw=(nw*s+ow*t)/10000;
530 bh=(nh*s+oh*t)/10000;
531 if(BORDERWIDTH*2<bw && BORDERWIDTH*2<bh){
532 dc.drawHashBox(bx,by,bw,bh,BORDERWIDTH);
533 getApp()->flush(true);
534 FXThread::sleep(pause);
535 dc.drawHashBox(bx,by,bw,bh,BORDERWIDTH);
536 getApp()->flush(true);
537 }
538 }
539 }
540 }
541
542
543 // Handle repaint
onPaint(FXObject *,FXSelector,void * ptr)544 long FXMDIChild::onPaint(FXObject*,FXSelector,void* ptr){
545 FXEvent *ev=(FXEvent*)ptr;
546 FXint xx,yy,th,titlespace,letters,dots,dotspace;
547 FXint fh,mh,bh,bw,mw;
548
549 // If box is shown, hide it temporarily
550 if(mode&DRAG_INVERTED) drawRubberBox(newx,newy,neww,newh);
551
552 {
553 FXDCWindow dc(this,ev);
554
555 // Draw MDIChild background
556 dc.setForeground(baseColor);
557 dc.fillRectangle(ev->rect.x,ev->rect.y,ev->rect.w,ev->rect.h);
558
559 // Only draw stuff when not maximized
560 if(!(options&MDI_MAXIMIZED)){
561
562 // Compute sizes
563 fh=font->getFontHeight();
564 mw=windowbtn->getDefaultWidth();
565 mh=windowbtn->getDefaultHeight();
566 bw=deletebtn->getDefaultWidth();
567 bh=deletebtn->getDefaultHeight();
568 th=FXMAX3(fh,mh,bh)+2;
569
570 // Draw outer border
571 dc.setForeground(baseColor);
572 dc.fillRectangle(0,0,width-1,1);
573 dc.fillRectangle(0,0,1,height-2);
574 dc.setForeground(hiliteColor);
575 dc.fillRectangle(1,1,width-2,1);
576 dc.fillRectangle(1,1,1,height-2);
577 dc.setForeground(shadowColor);
578 dc.fillRectangle(1,height-2,width-1,1);
579 dc.fillRectangle(width-2,1,1,height-2);
580 dc.setForeground(borderColor);
581 dc.fillRectangle(0,height-1,width,1);
582 dc.fillRectangle(width-1,0,1,height);
583
584 // Draw title background
585 dc.setForeground(isActive() ? (hasFocus() ? titleBackColor : shadowColor) : backColor);
586 dc.fillRectangle(BORDERWIDTH,BORDERWIDTH,width-BORDERWIDTH*2,th);
587
588 // Draw title
589 if(!title.empty()){
590 xx=BORDERWIDTH+mw+2+4;
591 yy=BORDERWIDTH+font->getFontAscent()+(th-fh)/2;
592
593 // Compute space for title
594 titlespace=width-mw-3*bw-(BORDERWIDTH<<1)-2-4-4-6-2;
595
596 dots=0;
597 letters=title.length();
598
599 // Title too large for space
600 if(font->getTextWidth(title.text(),letters)>titlespace){
601 dotspace=titlespace-font->getTextWidth("...",3);
602 while(letters>0 && font->getTextWidth(title.text(),letters)>dotspace) letters--;
603 dots=3;
604 if(letters==0){
605 letters=1;
606 dots=0;
607 }
608 }
609
610 // Draw as much of the title as possible
611 dc.setForeground(isActive() ? titleColor : borderColor);
612 dc.setFont(font);
613 dc.drawText(xx,yy,title.text(),letters);
614 dc.drawText(xx+font->getTextWidth(title.text(),letters),yy,"...",dots);
615 }
616
617 // Draw inner border
618 if(!(options&MDI_MINIMIZED)){
619 dc.setForeground(shadowColor);
620 dc.fillRectangle(BORDERWIDTH,BORDERWIDTH+th,width-BORDERWIDTH*2-1,1);
621 dc.fillRectangle(BORDERWIDTH,BORDERWIDTH+th,1,height-th-BORDERWIDTH*2-1);
622 dc.setForeground(borderColor);
623 dc.fillRectangle(BORDERWIDTH+1,BORDERWIDTH+th+1,width-BORDERWIDTH*2-3,1);
624 dc.fillRectangle(BORDERWIDTH+1,BORDERWIDTH+th+1,1,height-th-BORDERWIDTH*2-3);
625 dc.setForeground(hiliteColor);
626 dc.fillRectangle(BORDERWIDTH,height-BORDERWIDTH-1,width-BORDERWIDTH*2,1);
627 dc.fillRectangle(width-BORDERWIDTH-1,BORDERWIDTH+th,1,height-th-BORDERWIDTH*2);
628 dc.setForeground(baseColor);
629 dc.fillRectangle(BORDERWIDTH+1,height-BORDERWIDTH-2,width-BORDERWIDTH*2-2,1);
630 dc.fillRectangle(width-BORDERWIDTH-2,BORDERWIDTH+th+1,1,height-th-BORDERWIDTH*2-2);
631 }
632 }
633 }
634
635 // Redraw the box over freshly painted window
636 if(mode&DRAG_INVERTED) drawRubberBox(newx,newy,neww,newh);
637
638 return 1;
639 }
640
641
642 // Find out where window was grabbed
where(FXint x,FXint y)643 FXuchar FXMDIChild::where(FXint x,FXint y){
644 FXuchar code=DRAG_NONE;
645 FXint fh,mh,bh,th;
646 fh=font->getFontHeight();
647 mh=windowbtn->getDefaultHeight();
648 bh=deletebtn->getDefaultHeight();
649 th=FXMAX3(fh,mh,bh)+2;
650 if(!isMinimized() && x<HANDLESIZE) code|=DRAG_LEFT;
651 if(!isMinimized() && width-HANDLESIZE<=x) code|=DRAG_RIGHT;
652 if(!isMinimized() && y<HANDLESIZE) code|=DRAG_TOP;
653 if(!isMinimized() && height-HANDLESIZE<=y) code|=DRAG_BOTTOM;
654 if(BORDERWIDTH<=x && x<=width-BORDERWIDTH && BORDERWIDTH<=y && y<BORDERWIDTH+th) code=DRAG_TITLE;
655 return code;
656 }
657
658
659 // Focus on widget itself
onFocusSelf(FXObject *,FXSelector,void * ptr)660 long FXMDIChild::onFocusSelf(FXObject*,FXSelector,void* ptr){
661 setFocus();
662 if(contentWindow()) contentWindow()->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
663 return 1;
664 // if(contentWindow() && contentWindow()->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr)) return 1;
665 // setFocus();
666 // return 1; ///// FIXME See ScrollWindow /////
667 // FXWindow *child=contentWindow();
668 // return child && child->handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
669 }
670
671
672 // Gained focus
onFocusIn(FXObject * sender,FXSelector sel,void * ptr)673 long FXMDIChild::onFocusIn(FXObject* sender,FXSelector sel,void* ptr){
674 FXint fh,mh,bh,th;
675 FXComposite::onFocusIn(sender,sel,ptr);
676 fh=font->getFontHeight();
677 mh=windowbtn->getDefaultHeight();
678 bh=deletebtn->getDefaultHeight();
679 th=FXMAX3(fh,mh,bh)+2;
680 windowbtn->setBackColor(isActive() ? titleBackColor : backColor);
681 update(BORDERWIDTH,BORDERWIDTH,width-(BORDERWIDTH<<1),th);
682 return 1;
683 }
684
685
686 // Lost focus
onFocusOut(FXObject * sender,FXSelector sel,void * ptr)687 long FXMDIChild::onFocusOut(FXObject* sender,FXSelector sel,void* ptr){
688 FXint fh,mh,bh,th;
689 FXComposite::onFocusOut(sender,sel,ptr);
690 fh=font->getFontHeight();
691 mh=windowbtn->getDefaultHeight();
692 bh=deletebtn->getDefaultHeight();
693 th=FXMAX3(fh,mh,bh)+2;
694 windowbtn->setBackColor(isActive() ? shadowColor : backColor);
695 update(BORDERWIDTH,BORDERWIDTH,width-(BORDERWIDTH<<1),th);
696 return 1;
697 }
698
699
700 // Pressed LEFT button
onLeftBtnPress(FXObject *,FXSelector,void * ptr)701 long FXMDIChild::onLeftBtnPress(FXObject*,FXSelector,void* ptr){
702 FXEvent *event=(FXEvent*)ptr;
703 flags&=~FLAG_TIP;
704 handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
705 if(isEnabled()){
706 grab();
707 if(target && target->tryHandle(this,FXSEL(SEL_LEFTBUTTONPRESS,message),ptr)) return 1;
708 if(event->click_count==1){
709 mode=where(event->win_x,event->win_y);
710 if(mode!=DRAG_NONE){
711 if(mode&(DRAG_TOP|DRAG_TITLE)) spoty=event->win_y;
712 else if(mode&DRAG_BOTTOM) spoty=event->win_y-height;
713 if(mode&(DRAG_LEFT|DRAG_TITLE)) spotx=event->win_x;
714 else if(mode&DRAG_RIGHT) spotx=event->win_x-width;
715 xoff=event->win_x+xpos-event->root_x;
716 yoff=event->win_y+ypos-event->root_y;
717 newx=xpos;
718 newy=ypos;
719 neww=width;
720 newh=height;
721 if(!(options&MDI_TRACKING)){
722 if(!(mode&DRAG_TITLE)){
723 drawRubberBox(newx,newy,neww,newh);
724 mode|=DRAG_INVERTED;
725 }
726 }
727 }
728 }
729 return 1;
730 }
731 return 0;
732 }
733
734
735 // Released LEFT button
onLeftBtnRelease(FXObject *,FXSelector,void * ptr)736 long FXMDIChild::onLeftBtnRelease(FXObject*,FXSelector,void* ptr){
737 FXEvent *event=(FXEvent*)ptr;
738 if(isEnabled()){
739 ungrab();
740 if(target && target->tryHandle(this,FXSEL(SEL_LEFTBUTTONRELEASE,message),ptr)) return 1;
741 if(event->click_count==1){
742 if(mode!=DRAG_NONE){
743 if(!(options&MDI_TRACKING)){
744 if(mode&DRAG_INVERTED) drawRubberBox(newx,newy,neww,newh);
745 position(newx,newy,neww,newh);
746 }
747 mode=DRAG_NONE;
748 recalc();
749 }
750 }
751 else if(event->click_count==2){
752 if(options&MDI_MINIMIZED){
753 animateRectangles(xpos,ypos,width,height,normalPosX,normalPosY,normalWidth,normalHeight);
754 restore(TRUE);
755 }
756 else if(options&MDI_MAXIMIZED){
757 animateRectangles(xpos,ypos,width,height,normalPosX,normalPosY,normalWidth,normalHeight);
758 restore(TRUE);
759 }
760 else{
761 animateRectangles(xpos,ypos,width,height,0,0,getParent()->getWidth(),getParent()->getHeight());
762 maximize(TRUE);
763 }
764 }
765 return 1;
766 }
767 return 0;
768 }
769
770
771 // Moved
onMotion(FXObject *,FXSelector,void * ptr)772 long FXMDIChild::onMotion(FXObject*,FXSelector,void* ptr){
773 FXEvent *event=(FXEvent*)ptr;
774 FXint tmp,mousex,mousey;
775 FXint oldx,oldy,oldw,oldh;
776 if(mode!=DRAG_NONE){
777
778 // Mouse in FXMDIClient's coordinates
779 mousex=event->root_x+xoff;
780 mousey=event->root_y+yoff;
781
782 // Keep inside FXMDIClient
783 if(mousex<0) mousex=0;
784 if(mousey<0) mousey=0;
785 if(mousex>=getParent()->getWidth()) mousex=getParent()->getWidth()-1;
786 if(mousey>=getParent()->getHeight()) mousey=getParent()->getHeight()-1;
787
788 // Remember old box
789 oldx=newx;
790 oldy=newy;
791 oldw=neww;
792 oldh=newh;
793
794 // Dragging title
795 if(mode&DRAG_TITLE){
796 if(!event->moved) return 1;
797 newy=mousey-spoty;
798 newx=mousex-spotx;
799 setDragCursor(getApp()->getDefaultCursor(DEF_MOVE_CURSOR));
800 }
801
802 // Dragging sides
803 else{
804
805 // Vertical
806 if(mode&DRAG_TOP){
807 tmp=newh+newy-mousey+spoty;
808 if(tmp>=MINHEIGHT){ newh=tmp; newy=mousey-spoty; }
809 }
810 else if(mode&DRAG_BOTTOM){
811 tmp=mousey-spoty-newy;
812 if(tmp>=MINHEIGHT){ newh=tmp; }
813 }
814
815 // Horizontal
816 if(mode&DRAG_LEFT){
817 tmp=neww+newx-mousex+spotx;
818 if(tmp>=MINWIDTH){ neww=tmp; newx=mousex-spotx; }
819 }
820 else if(mode&DRAG_RIGHT){
821 tmp=mousex-spotx-newx;
822 if(tmp>=MINWIDTH){ neww=tmp; }
823 }
824 }
825
826 // Move box
827 if(!(options&MDI_TRACKING)){
828 if(mode&DRAG_INVERTED) drawRubberBox(oldx,oldy,oldw,oldh);
829 drawRubberBox(newx,newy,neww,newh);
830 mode|=DRAG_INVERTED;
831 }
832 else{
833 position(newx,newy,neww,newh);
834 }
835 return 1;
836 }
837
838 // Othersize just change cursor based on location
839 changeCursor(event->win_x,event->win_y);
840 return 0;
841 }
842
843
844 // Pressed MIDDLE button
onMiddleBtnPress(FXObject *,FXSelector,void * ptr)845 long FXMDIChild::onMiddleBtnPress(FXObject*,FXSelector,void* ptr){
846 flags&=~FLAG_TIP;
847 handle(this,FXSEL(SEL_FOCUS_SELF,0),ptr);
848 if(isEnabled()){
849 grab();
850 if(target && target->tryHandle(this,FXSEL(SEL_MIDDLEBUTTONPRESS,message),ptr)) return 1;
851 return 1;
852 }
853 return 0;
854 }
855
856
857 // Released MIDDLE button
onMiddleBtnRelease(FXObject *,FXSelector,void * ptr)858 long FXMDIChild::onMiddleBtnRelease(FXObject*,FXSelector,void* ptr){
859 if(isEnabled()){
860 ungrab();
861 if(target && target->tryHandle(this,FXSEL(SEL_MIDDLEBUTTONRELEASE,message),ptr)) return 1;
862 return 1;
863 }
864 return 0;
865 }
866
867
868 // Pressed RIGHT button
onRightBtnPress(FXObject *,FXSelector,void * ptr)869 long FXMDIChild::onRightBtnPress(FXObject*,FXSelector,void* ptr){
870 flags&=~FLAG_TIP;
871 if(isEnabled()){
872 grab();
873 if(target && target->tryHandle(this,FXSEL(SEL_RIGHTBUTTONPRESS,message),ptr)) return 1;
874 lower();
875 return 1;
876 }
877 return 0;
878 }
879
880
881 // Released RIGHT button
onRightBtnRelease(FXObject *,FXSelector,void * ptr)882 long FXMDIChild::onRightBtnRelease(FXObject*,FXSelector,void* ptr){
883 if(isEnabled()){
884 ungrab();
885 if(target && target->tryHandle(this,FXSEL(SEL_RIGHTBUTTONRELEASE,message),ptr)) return 1;
886 return 1;
887 }
888 return 0;
889 }
890
891
892 // Update value from a message
onCmdSetStringValue(FXObject *,FXSelector,void * ptr)893 long FXMDIChild::onCmdSetStringValue(FXObject*,FXSelector,void* ptr){
894 setTitle(*((FXString*)ptr));
895 return 1;
896 }
897
898
899 // Obtain value from text field
onCmdGetStringValue(FXObject *,FXSelector,void * ptr)900 long FXMDIChild::onCmdGetStringValue(FXObject*,FXSelector,void* ptr){
901 *((FXString*)ptr)=getTitle();
902 return 1;
903 }
904
905
906 // Update icon from a message
onCmdSetIconValue(FXObject *,FXSelector,void * ptr)907 long FXMDIChild::onCmdSetIconValue(FXObject*,FXSelector,void* ptr){
908 setIcon(*((FXIcon**)ptr));
909 return 1;
910 }
911
912
913 // Obtain icon from text field
onCmdGetIconValue(FXObject *,FXSelector,void * ptr)914 long FXMDIChild::onCmdGetIconValue(FXObject*,FXSelector,void* ptr){
915 *((FXIcon**)ptr)=getIcon();
916 return 1;
917 }
918
919
920 // Window was selected
onSelected(FXObject *,FXSelector,void * ptr)921 long FXMDIChild::onSelected(FXObject*,FXSelector,void* ptr){ // FIXME
922 if(!(flags&FLAG_ACTIVE)){
923 if(target) target->tryHandle(this,FXSEL(SEL_SELECTED,message),ptr);
924 windowbtn->setBackColor(hasFocus() ? titleBackColor : shadowColor);
925 flags|=FLAG_ACTIVE;
926 recalc();
927 update();
928 }
929 return 1;
930 }
931
932
933 // Window was deselected
onDeselected(FXObject *,FXSelector,void * ptr)934 long FXMDIChild::onDeselected(FXObject*,FXSelector,void* ptr){ // FIXME
935 if(flags&FLAG_ACTIVE){
936 if(target) target->tryHandle(this,FXSEL(SEL_DESELECTED,message),ptr);
937 windowbtn->setBackColor(backColor);
938 flags&=~FLAG_ACTIVE;
939 recalc();
940 update();
941 }
942 return 1;
943 }
944
945
946 /*******************************************************************************/
947
948
949 // Restore window command
onCmdRestore(FXObject *,FXSelector,void *)950 long FXMDIChild::onCmdRestore(FXObject*,FXSelector,void*){
951 animateRectangles(xpos,ypos,width,height,normalPosX,normalPosY,normalWidth,normalHeight);
952 restore(TRUE);
953 return 1;
954 }
955
956
957 // Update restore command
onUpdRestore(FXObject * sender,FXSelector,void *)958 long FXMDIChild::onUpdRestore(FXObject* sender,FXSelector,void*){
959 sender->handle(this,isMinimized()||isMaximized()?FXSEL(SEL_COMMAND,ID_ENABLE):FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
960 return 1;
961 }
962
963
964 // Update MDI restore button on menu bar
onUpdMenuRestore(FXObject * sender,FXSelector,void *)965 long FXMDIChild::onUpdMenuRestore(FXObject* sender,FXSelector,void*){
966 if(isMaximized()){
967 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
968 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
969 }
970 else{
971 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
972 }
973 return 1;
974 }
975
976
977 // Maximize window command
onCmdMaximize(FXObject *,FXSelector,void *)978 long FXMDIChild::onCmdMaximize(FXObject*,FXSelector,void*){
979 animateRectangles(xpos,ypos,width,height,0,0,getParent()->getWidth(),getParent()->getHeight());
980 maximize(TRUE);
981 return 1;
982 }
983
984
985 // Update maximized command
onUpdMaximize(FXObject * sender,FXSelector,void *)986 long FXMDIChild::onUpdMaximize(FXObject* sender,FXSelector,void*){
987 sender->handle(this,isMaximized()?FXSEL(SEL_COMMAND,ID_DISABLE):FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
988 return 1;
989 }
990
991
992 // Minimize window command
onCmdMinimize(FXObject *,FXSelector,void *)993 long FXMDIChild::onCmdMinimize(FXObject*,FXSelector,void*){
994 animateRectangles(xpos,ypos,width,height,iconPosX,iconPosY,getDefaultWidth(),getDefaultHeight());
995 minimize(TRUE);
996 return 1;
997 }
998
999
1000 // Update minimized command
onUpdMinimize(FXObject * sender,FXSelector,void *)1001 long FXMDIChild::onUpdMinimize(FXObject* sender,FXSelector,void*){
1002 sender->handle(this,isMinimized()?FXSEL(SEL_COMMAND,ID_DISABLE):FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1003 return 1;
1004 }
1005
1006
1007 // Update MDI minimized button on menu bar
onUpdMenuMinimize(FXObject * sender,FXSelector,void *)1008 long FXMDIChild::onUpdMenuMinimize(FXObject* sender,FXSelector,void*){
1009 if(isMaximized()){
1010 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
1011 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1012 }
1013 else{
1014 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
1015 }
1016 return 1;
1017 }
1018
1019
1020 // Close window after asking FXMDIChild's target; returns 1 if closed
onCmdClose(FXObject *,FXSelector,void *)1021 long FXMDIChild::onCmdClose(FXObject*,FXSelector,void*){
1022 return close(TRUE);
1023 }
1024
1025
1026 // Update close command
onUpdClose(FXObject * sender,FXSelector,void *)1027 long FXMDIChild::onUpdClose(FXObject* sender,FXSelector,void*){
1028 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1029 return 1;
1030 }
1031
1032
1033 // Update MDI close button on menu bar
onUpdMenuClose(FXObject * sender,FXSelector,void *)1034 long FXMDIChild::onUpdMenuClose(FXObject* sender,FXSelector,void*){
1035 if(isMaximized()){
1036 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1037 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
1038 }
1039 else{
1040 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
1041 }
1042 return 1;
1043 }
1044
1045
1046 // Update window menu button
onUpdWindow(FXObject * sender,FXSelector,void *)1047 long FXMDIChild::onUpdWindow(FXObject* sender,FXSelector,void*){
1048 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1049 return 1;
1050 }
1051
1052
1053 // Update MDI window menu button on menu bar
onUpdMenuWindow(FXObject * sender,FXSelector,void *)1054 long FXMDIChild::onUpdMenuWindow(FXObject* sender,FXSelector,void*){
1055 FXIcon *icon=getIcon();
1056 if(isMaximized()){
1057 sender->handle(this,FXSEL(SEL_COMMAND,ID_SHOW),NULL);
1058 sender->handle(this,FXSEL(SEL_COMMAND,ID_ENABLE),NULL);
1059 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETICONVALUE),(void*)&icon);
1060 }
1061 else{
1062 sender->handle(this,FXSEL(SEL_COMMAND,ID_HIDE),NULL);
1063 }
1064 return 1;
1065 }
1066
1067
1068 // Set base color
setBaseColor(FXColor clr)1069 void FXMDIChild::setBaseColor(FXColor clr){
1070 if(baseColor!=clr){
1071 baseColor=clr;
1072 update();
1073 }
1074 }
1075
1076
1077 // Set highlight color
setHiliteColor(FXColor clr)1078 void FXMDIChild::setHiliteColor(FXColor clr){
1079 if(hiliteColor!=clr){
1080 hiliteColor=clr;
1081 update();
1082 }
1083 }
1084
1085
1086 // Set shadow color
setShadowColor(FXColor clr)1087 void FXMDIChild::setShadowColor(FXColor clr){
1088 if(shadowColor!=clr){
1089 shadowColor=clr;
1090 update();
1091 }
1092 }
1093
1094
1095 // Set border color
setBorderColor(FXColor clr)1096 void FXMDIChild::setBorderColor(FXColor clr){
1097 if(borderColor!=clr){
1098 borderColor=clr;
1099 update();
1100 }
1101 }
1102
1103
1104 // Set title color
setTitleColor(FXColor clr)1105 void FXMDIChild::setTitleColor(FXColor clr){
1106 if(titleColor!=clr){
1107 titleColor=clr;
1108 update();
1109 }
1110 }
1111
1112
1113 // Set title color
setTitleBackColor(FXColor clr)1114 void FXMDIChild::setTitleBackColor(FXColor clr){
1115 if(titleBackColor!=clr){
1116 titleBackColor=clr;
1117 update();
1118 }
1119 }
1120
1121
1122 // Set new window title
setTitle(const FXString & name)1123 void FXMDIChild::setTitle(const FXString& name){
1124 if(title!=name){
1125 title=name;
1126 update();
1127 }
1128 }
1129
1130
1131 // Delegate all unhandled messages to content window or MDI child's target,
1132 // except for those messages with ID's which belong to the MDI child itself.
onDefault(FXObject * sender,FXSelector sel,void * ptr)1133 long FXMDIChild::onDefault(FXObject* sender,FXSelector sel,void* ptr){
1134 if(FXMDIChild::ID_LAST<=FXSELID(sel)){
1135 if(contentWindow() && contentWindow()->tryHandle(sender,sel,ptr)) return 1;
1136 return target && target->tryHandle(sender,sel,ptr);
1137 }
1138 return 0;
1139 }
1140
1141
1142 // Get icon used for the menu button
getIcon() const1143 FXIcon *FXMDIChild::getIcon() const {
1144 return windowbtn->getIcon();
1145 }
1146
1147
1148 // Change icon used for window menu button
setIcon(FXIcon * ic)1149 void FXMDIChild::setIcon(FXIcon* ic){
1150 windowbtn->setIcon(ic);
1151 }
1152
1153
1154 // Obtain window menu
getMenu() const1155 FXPopup* FXMDIChild::getMenu() const {
1156 return windowbtn->getMenu();
1157 }
1158
1159
1160 // Change window menu
setMenu(FXPopup * menu)1161 void FXMDIChild::setMenu(FXPopup* menu){
1162 windowbtn->setMenu(menu);
1163 }
1164
1165
1166 // Change the font
setFont(FXFont * fnt)1167 void FXMDIChild::setFont(FXFont *fnt){
1168 if(!fnt){ fxerror("%s::setFont: NULL font specified.\n",getClassName()); }
1169 if(font!=fnt){
1170 font=fnt;
1171 recalc();
1172 update();
1173 }
1174 }
1175
1176
1177 // Set tracking instead of just outline
setTracking(FXbool tracking)1178 void FXMDIChild::setTracking(FXbool tracking){
1179 if(tracking) options|=MDI_TRACKING; else options&=~MDI_TRACKING;
1180 }
1181
1182
1183 // Return true if tracking
getTracking() const1184 FXbool FXMDIChild::getTracking() const {
1185 return (options&MDI_TRACKING)!=0;
1186 }
1187
1188
1189 // Save object to stream
save(FXStream & store) const1190 void FXMDIChild::save(FXStream& store) const {
1191 FXComposite::save(store);
1192 store << title;
1193 store << windowbtn;
1194 store << minimizebtn;
1195 store << restorebtn;
1196 store << maximizebtn;
1197 store << deletebtn;
1198 store << font;
1199 store << baseColor;
1200 store << hiliteColor;
1201 store << shadowColor;
1202 store << borderColor;
1203 store << titleColor;
1204 store << titleBackColor;
1205 store << iconPosX;
1206 store << iconPosY;
1207 store << iconWidth;
1208 store << iconHeight;
1209 store << normalPosX;
1210 store << normalPosY;
1211 store << normalWidth;
1212 store << normalHeight;
1213 }
1214
1215
1216 // Load object from stream
load(FXStream & store)1217 void FXMDIChild::load(FXStream& store){
1218 FXComposite::load(store);
1219 store >> title;
1220 store >> windowbtn;
1221 store >> minimizebtn;
1222 store >> restorebtn;
1223 store >> maximizebtn;
1224 store >> deletebtn;
1225 store >> font;
1226 store >> baseColor;
1227 store >> hiliteColor;
1228 store >> shadowColor;
1229 store >> borderColor;
1230 store >> titleColor;
1231 store >> titleBackColor;
1232 store >> iconPosX;
1233 store >> iconPosY;
1234 store >> iconWidth;
1235 store >> iconHeight;
1236 store >> normalPosX;
1237 store >> normalPosY;
1238 store >> normalWidth;
1239 store >> normalHeight;
1240 }
1241
1242
1243 // Destruct thrashes the pointers
~FXMDIChild()1244 FXMDIChild::~FXMDIChild(){
1245 if(((FXMDIClient*)getParent())->active==this) ((FXMDIClient*)getParent())->active=NULL;
1246 windowbtn=(FXMenuButton*)-1L;
1247 minimizebtn=(FXButton*)-1L;
1248 restorebtn=(FXButton*)-1L;
1249 maximizebtn=(FXButton*)-1L;
1250 deletebtn=(FXButton*)-1L;
1251 font=(FXFont*)-1L;
1252 }
1253
1254 }
1255