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