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