2 Copyright (C) 1996 Scott W. Sadler
10 03-Mar-96 1.0; Scott W. Sadler (ssadler@cisco.com)
18 #include <Xm/RowColumn.h>
19 #include <Xm/SeparatoG.h>
20 #include <Xm/PushBG.h>
21 #include <X11/Shell.h>
22 #include <X11/cursorfont.h>
23 #include "XsMotifWindow.h"
24 #include "XsResizeOutline.h"
25 #include "XsMoveOutline.h"
26 #include "xs_motif_icon.xbm"
30 const int BorderSize_ = 6;
31 const int ButtonSize_ = 23;
32 const int IconSize_ = 70;
35 ----------------------------------------------------------------------------
41 _XsMotifBase::_XsMotifBase (const char *name, XsMotifWindow *win) :
55 _XsMotifBase::~_XsMotifBase ( )
58 XtReleaseGC (_base, _topShadowGC);
61 XtReleaseGC (_base, _bottomShadowGC);
66 void _XsMotifBase::show ( )
70 // Install event handler
72 XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
74 // Call the base-class
76 XsComponent::show ( );
81 const char* _XsMotifBase::className ( ) const
83 return ("_XsMotifBase");
86 // _componentDestroyed ( )
88 void _XsMotifBase::_componentDestroyed ( )
94 XtReleaseGC (_base, _topShadowGC);
97 XtReleaseGC (_base, _bottomShadowGC);
102 // Call the base-class
104 XsComponent::_componentDestroyed ( );
109 void _XsMotifBase::_drawShadows (Position x, Position y, Dimension width,
110 Dimension height, Dimension thick, Boolean reverse)
116 XSegment segs[nsegs];
120 // Work out the graphics contexts
122 topShadowGC = (reverse == False) ? _topShadowGC : _bottomShadowGC;
123 bottomShadowGC = (reverse == False) ? _bottomShadowGC : _topShadowGC;
125 for (int loop = 0; loop < thick; loop++)
134 segs[0].x1 = x + loop;
135 segs[0].y1 = y + loop;
136 segs[0].x2 = x + width - loop - 2;
137 segs[0].y2 = y + loop;
139 // Down the left side
141 segs[1].x1 = x + loop;
142 segs[1].y1 = y + loop + 1;
143 segs[1].x2 = x + loop;
144 segs[1].y2 = y + height - loop - 2;
146 XDrawSegments (XtDisplay (_base), XtWindow (_base), topShadowGC, segs, nsegs);
149 BOTTOM SHADOW DRAWING
154 segs[0].x1 = x + loop;
155 segs[0].y1 = y + height - loop - 1;
156 segs[0].x2 = x + width - loop - 1;
157 segs[0].y2 = y + height - loop - 1;
159 // Down the right side
161 segs[1].x1 = x + width - loop - 1;
162 segs[1].y1 = y + loop;
163 segs[1].x2 = x + width - loop - 1;
164 segs[1].y2 = y + height - loop - 1;
166 XDrawSegments (XtDisplay (_base), XtWindow (_base), bottomShadowGC, segs, nsegs);
172 void _XsMotifBase::_drawLine (Position x1, Position y1, Position x2, Position y2, GC &gc)
175 XDrawLine (XtDisplay (_base), XtWindow (_base), gc, x1, y1, x2, y2);
180 void _XsMotifBase::_map ( )
183 // Create the graphics contexts
185 unsigned long valuemask;
190 XtVaGetValues (_win->base ( ), XmNtopShadowColor, &topShadow, XmNbottomShadowColor,
191 &bottomShadow, NULL);
193 // Create the graphics contexts
195 valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
196 values.line_width = 0;
197 values.graphics_exposures = False;
199 values.foreground = topShadow;
200 _topShadowGC = XtGetGC (_base, valuemask, &values);
202 values.foreground = bottomShadow;
203 _bottomShadowGC = XtGetGC (_base, valuemask, &values);
208 void _XsMotifBase::_mapEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
210 if (event->type == MapNotify)
212 _XsMotifBase *obj = (_XsMotifBase*)clientData;
215 // Remove the event handler
217 XtRemoveEventHandler (obj->_base, StructureNotifyMask, False, obj->_mapEventHandler, clientData);
222 ----------------------------------------------------------------------------
226 Cursor _XsMotifComponent::_cursors[_XsMotifComponent::NumCursors];
228 int _XsMotifComponent::_mutex = 0;
230 XtResource _XsMotifComponent::_resourceList[] = {
236 XtOffset (_XsMotifComponent*, _borderSize),
238 (XtPointer)BorderSize_
245 XtOffset (_XsMotifComponent*, _buttonSize),
247 (XtPointer)ButtonSize_
253 _XsMotifComponent::_XsMotifComponent (const char *name, XsMotifWindow *win,
254 Widget parent) : _XsMotifBase (name, win)
257 // Create cursors (if necessary)
262 Display *dpy = XtDisplay (win->base ( ));
264 _cursors[TopCursor] = XCreateFontCursor (dpy, XC_top_side);
265 _cursors[BottomCursor] = XCreateFontCursor (dpy, XC_bottom_side);
266 _cursors[LeftCursor] = XCreateFontCursor (dpy, XC_left_side);
267 _cursors[RightCursor] = XCreateFontCursor (dpy, XC_right_side);
268 _cursors[TopLeftCursor] = XCreateFontCursor (dpy, XC_top_left_corner);
269 _cursors[TopRightCursor] = XCreateFontCursor (dpy, XC_top_right_corner);
270 _cursors[BottomLeftCursor] = XCreateFontCursor (dpy, XC_bottom_left_corner);
271 _cursors[BottomRightCursor] = XCreateFontCursor (dpy, XC_bottom_right_corner);
276 // Create the component
278 _base = XtVaCreateWidget (name, widgetClass, (parent != 0) ? parent : _win->base ( ), NULL);
280 // Install destroy handler
282 _installDestroyHandler ( );
286 _getResources (_resourceList, XtNumber (_resourceList));
288 // Compute the corner size
290 _cornerSize = _buttonSize + _borderSize;
292 // Install event handlers
294 XtAddEventHandler (_base, ExposureMask, False, _exposeEventHandler, (XtPointer)this);
295 XtAddEventHandler (_base, ButtonPressMask | ButtonReleaseMask | Button1MotionMask | Button2MotionMask, False, _inputEventHandler, (XtPointer)this);
300 _XsMotifComponent::~_XsMotifComponent ( )
307 const char* _XsMotifComponent::className ( ) const
309 return ("_XsMotifComponent");
314 void _XsMotifComponent::_input (XEvent*)
319 // _exposeEventHandler
321 void _XsMotifComponent::_exposeEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
323 _XsMotifComponent *obj = (_XsMotifComponent*)clientData;
325 if (event->xexpose.count == 0)
326 obj->_expose (event);
329 // _inputEventHandler
331 void _XsMotifComponent::_inputEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
333 _XsMotifComponent *obj = (_XsMotifComponent*)clientData;
338 ----------------------------------------------------------------------------
344 _XsMotifCorner::_XsMotifCorner (const char *name, XsMotifWindow *win, Corner corner)
345 : _XsMotifComponent (name, win)
352 // Configure component
354 XtVaSetValues (_base, XmNwidth, _cornerSize, XmNheight, _cornerSize,
355 XmNborderWidth, (Dimension)0, NULL);
360 _XsMotifCorner::~_XsMotifCorner ( )
367 const char *_XsMotifCorner::className ( ) const
369 return ("_XsMotifCorner");
374 void _XsMotifCorner::_expose (XEvent*)
378 // Get the size of the corner
380 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
384 _drawShadows (0, 0, w, h, 1);
386 // Draw the extra lines and relief
392 _drawLine (1, 1, w - 2, 1, _topShadowGC);
393 _drawLine (1, 1, 1, h - 2, _topShadowGC);
397 _drawLine (_borderSize - 1, _borderSize - 1, _borderSize +
398 _buttonSize - 2, _borderSize - 1, _bottomShadowGC);
400 _drawLine (_borderSize - 1, _borderSize - 1, _borderSize - 1,
401 _borderSize + _buttonSize - 2, _bottomShadowGC);
407 _drawLine (1, 1, w - 2, 1, _topShadowGC);
408 _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
412 _drawLine (0, _borderSize - 1, _buttonSize - 1, _borderSize - 1,
415 _drawLine (w - _borderSize, _borderSize - 1, w - _borderSize,
416 _borderSize + _buttonSize - 2, _topShadowGC);
422 _drawLine (1, 1, 1, h - 2, _topShadowGC);
423 _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
427 _drawLine (_borderSize - 1, h - _borderSize, _borderSize +
428 _buttonSize - 2, h - _borderSize, _topShadowGC);
430 _drawLine (_borderSize - 1, 1, _borderSize - 1,
431 _buttonSize - 1, _bottomShadowGC);
437 _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
438 _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
442 _drawLine (1, h - _borderSize, _buttonSize, h - _borderSize,
445 _drawLine (w - _borderSize, 1, w - _borderSize,
446 _buttonSize - 1, _topShadowGC);
457 void _XsMotifCorner::_input (XEvent *event)
463 if (event->xbutton.button == 2)
465 XsMoveOutline move (_win->base ( ));
469 if (move.go ( ) != False)
472 // Relocate the window
474 _win->setPosition (move.x ( ), move.y ( ));
477 else if (event->xbutton.button == 3)
484 switch (event->xbutton.button)
489 _win->raise ( ); // Raise the window
498 // Figure kind of resize we are doing
502 if (_corner == TopLeft)
503 dir = XsResizeOutline::Up | XsResizeOutline::Left;
504 else if (_corner == TopRight)
505 dir = XsResizeOutline::Up | XsResizeOutline::Right;
506 else if (_corner == BottomLeft)
507 dir = XsResizeOutline::Down | XsResizeOutline::Left;
508 else if (_corner == BottomRight)
509 dir = XsResizeOutline::Down | XsResizeOutline::Right;
513 XsResizeOutline resize (_win->base ( ), dir);
514 resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
518 if (resize.go ( ) != False)
521 // Relocate the window
523 _win->setPosition (resize.x ( ), resize.y ( ));
524 _win->setSize (resize.width ( ), resize.height ( ));
533 void _XsMotifCorner::_map ( )
536 // Call the base-class
538 _XsMotifComponent::_map ( );
540 // Install the cursor
542 if (_corner == TopLeft)
543 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopLeftCursor]);
544 else if (_corner == TopRight)
545 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopRightCursor]);
546 else if (_corner == BottomLeft)
547 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomLeftCursor]);
548 else if (_corner == BottomRight)
549 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomRightCursor]);
555 ----------------------------------------------------------------------------
561 _XsMotifSide::_XsMotifSide (const char *name, XsMotifWindow *win, Side side) :
562 _XsMotifComponent (name, win)
568 _lastW = _lastH = -1;
570 // Configure component
577 XtVaSetValues (_base, XmNheight, _borderSize, XmNborderWidth,
584 XtVaSetValues (_base, XmNwidth, _borderSize, XmNborderWidth,
592 // Install event handler
594 XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
599 _XsMotifSide::~_XsMotifSide ( )
606 const char *_XsMotifSide::className ( ) const
608 return ("_XsMotifSide");
613 void _XsMotifSide::_expose (XEvent *event)
616 // Clear out the window first
619 XClearWindow (XtDisplay (_base), XtWindow (_base));
623 // Get the size of the side
625 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
629 _drawShadows (0, 0, w, h, 1);
631 // Draw the extra lines
637 _drawLine (1, 1, w - 2, 1, _topShadowGC);
642 _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
647 _drawLine (1, 1, 1, h - 2, _topShadowGC);
652 _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
662 void _XsMotifSide::_input (XEvent *event)
668 if (event->xbutton.button == 2)
670 XsMoveOutline move (_win->base ( ));
674 if (move.go ( ) != False)
677 // Relocate the window
679 _win->setPosition (move.x ( ), move.y ( ));
682 else if (event->xbutton.button == 3)
689 switch (event->xbutton.button)
694 _win->raise ( ); // Raise the window
703 // Figure kind of resize we are doing
708 dir = XsResizeOutline::Up;
709 else if (_side == Bottom)
710 dir = XsResizeOutline::Down;
711 else if (_side == Left)
712 dir = XsResizeOutline::Left;
713 else if (_side == Right)
714 dir = XsResizeOutline::Right;
718 XsResizeOutline resize (_win->base ( ), dir);
719 resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
723 if (resize.go ( ) != False)
726 // Relocate the window
728 _win->setPosition (resize.x ( ), resize.y ( ));
729 _win->setSize (resize.width ( ), resize.height ( ));
738 void _XsMotifSide::_map ( )
741 // Call the base-class
743 _XsMotifComponent::_map ( );
745 // Install the cursor
748 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopCursor]);
749 else if (_side == Bottom)
750 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomCursor]);
751 else if (_side == Left)
752 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[LeftCursor]);
753 else if (_side == Right)
754 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[RightCursor]);
761 void _XsMotifSide::_configure (XEvent *event)
763 XConfigureEvent *ce = (XConfigureEvent*)event;
766 Check if window has been resized. If so, generate an expose event
767 to redraw its contents.
770 if ((_lastW != ce->width) || (_lastH != ce->height))
772 if ((_base != 0) && XtIsManaged (_base))
773 XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
780 // _configureEventHandler
782 void _XsMotifSide::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
784 if (event->type == ConfigureNotify)
786 _XsMotifSide *obj = (_XsMotifSide*)clientData;
787 obj->_configure (event);
792 ----------------------------------------------------------------------------
798 _XsMotifButton::_XsMotifButton (const char *name, XsMotifWindow *win, Button button) :
799 _XsMotifComponent (name, win)
807 // Configure the component
809 XtVaSetValues (_base, XmNheight, _buttonSize, XmNwidth, _buttonSize,
810 XmNborderWidth, (Dimension)0, NULL);
815 _XsMotifButton::~_XsMotifButton ( )
822 void _XsMotifButton::redraw ( )
825 // Make sure component is viewable
827 if (!XtIsRealized (_base))
830 // Check if window is viewable
832 XWindowAttributes attrs;
833 XGetWindowAttributes (XtDisplay (_base), XtWindow (_base), &attrs);
835 if (attrs.map_state == IsViewable)
836 _expose (0); // Just pretend we got an expose event
841 const char *_XsMotifButton::className ( ) const
843 return ("_XsMotifButton");
848 void _XsMotifButton::_expose (XEvent *event)
852 // Get the size of the button
854 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
858 _drawShadows (0, 0, w, h, 1, _pressed);
860 // Draw the extra line
862 _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
864 // Check if we need to draw the decal
866 if ((_button != Maximize) && (event == 0))
869 // Compute the decal size
872 Boolean reverse = False;
878 dw = _buttonSize - 6;
889 dw = _buttonSize - 6;
892 if (_win->maximized ( ))
903 _drawShadows ((w / 2) - (dw / 2), (h / 2) - (dh / 2), dw, dh, 1, reverse);
908 void _XsMotifButton::_input (XEvent *event)
910 static Time lastTime = (Time)0;
916 if (event->xbutton.button == 1)
923 // Get double-click time
925 int multiClick = XtGetMultiClickTime (XtDisplay (_base));
927 // Check for double-click
929 if ((event->xbutton.time - lastTime) <= multiClick)
935 lastTime = event->xbutton.time;
937 // Redraw the button (pushed-in)
943 _win->popupMenu (False);
945 // The menu will consume the ButtonRelease, so fake one
951 else if ((_button == Minimize) || (_button == Maximize))
956 else if (event->xbutton.button == 2)
958 XsMoveOutline move (_win->base ( ));
962 if (move.go ( ) != False)
965 // Relocate the window
967 _win->setPosition (move.x ( ), move.y ( ));
970 else if (event->xbutton.button == 3)
977 if (event->xbutton.button == 1)
981 // Check if pointer is really in the window
983 XButtonEvent *b = &event->xbutton;
984 Dimension width, height;
985 Boolean inWindow = False;
987 XtVaGetValues (_base, XmNwidth, &width, XmNheight, &height, NULL);
988 if ((b->x >= 0) && (b->y >= 0) && (b->x < width) && (b->y < height))
991 if (_button == Minimize)
995 if (_win->minimized ( ))
1003 else if (_button == Maximize)
1007 if (_win->maximized ( ))
1023 void _XsMotifButton::_map ( )
1026 // Call the base-class
1028 _XsMotifComponent::_map ( );
1032 XRaiseWindow (XtDisplay (_base), XtWindow (_base));
1036 ----------------------------------------------------------------------------
1040 XtResource _XsMotifTitle::_resourceList[] = {
1046 XtOffset (_XsMotifTitle*, _titleString),
1054 sizeof (XFontStruct*),
1055 XtOffset (_XsMotifTitle*, _titleFont),
1057 "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
1063 _XsMotifTitle::_XsMotifTitle (const char *name, XsMotifWindow *win) :
1064 _XsMotifComponent (name, win)
1073 _lastW = _lastH = -1;
1077 _getResources (_resourceList, XtNumber (_resourceList));
1079 // Copy title string to local memory
1081 if (_titleString != 0)
1083 char *tmp = new char[strlen (_titleString) + 1];
1084 strcpy (tmp, _titleString);
1088 // Configure the title
1090 XtVaSetValues (_base, XmNheight, _buttonSize, XmNborderWidth,
1091 (Dimension)0, NULL);
1093 // Install event handler
1095 XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
1100 _XsMotifTitle::~_XsMotifTitle ( )
1103 XtReleaseGC (_base, _fontGC);
1105 delete [] _titleString;
1110 void _XsMotifTitle::setTitle (const char *title)
1112 assert (title != 0);
1114 delete [] _titleString;
1116 _titleString = new char[strlen (title) + 1];
1117 strcpy (_titleString, title);
1122 const char *_XsMotifTitle::className ( ) const
1124 return ("_XsMotifTitle");
1127 // _componentDestroyed
1129 void _XsMotifTitle::_componentDestroyed ( )
1135 XtReleaseGC (_base, _fontGC);
1141 _XsMotifComponent::_componentDestroyed ( );
1146 void _XsMotifTitle::_redraw ( )
1148 _expose (0); // Just pretend we got an expose event
1153 void _XsMotifTitle::_expose (XEvent *event)
1156 // Clear out the window first
1159 XClearWindow (XtDisplay (_base), XtWindow (_base));
1163 // Get the size of the button
1165 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
1169 _drawShadows (0, 0, w, h, 1, _pressed);
1171 // Draw the extra line
1173 _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
1175 // If this is an artificial event, no need continuing
1180 // Draw the text string
1182 const int LeftOffset = 5;
1183 const int TopOffset = 2;
1185 // Figure out the title
1187 const char *title = (_titleString != 0) ? _titleString : _win->name ( );
1189 if ((title != 0) && (title[0] != '\0'))
1191 int len = strlen (title);
1193 XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
1194 LeftOffset, TopOffset + _titleFont->ascent, title, len);
1200 void _XsMotifTitle::_input (XEvent *event)
1202 switch (event->type)
1206 switch (event->xbutton.button)
1216 XsMoveOutline move (_win->base ( ));
1220 if (move.go ( ) != False)
1223 // Relocate the window
1225 _win->setPosition (move.x ( ), move.y ( ));
1231 _win->popupMenu ( );
1239 switch (event->xbutton.button)
1255 XsMoveOutline move (_win->base ( ));
1259 if (move.go ( ) != False)
1262 // Relocate the window
1264 _win->setPosition (move.x ( ), move.y ( ));
1266 // Redraw the title bar
1278 void _XsMotifTitle::_map ( )
1281 // Call the base-class
1283 _XsMotifComponent::_map ( );
1287 XRaiseWindow (XtDisplay (_base), XtWindow (_base));
1289 unsigned long valuemask;
1296 XtVaGetValues (_win->base ( ), XmNforeground, &foreground, XmNbackground, &background, NULL);
1298 // Create the font graphics context
1300 valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
1302 values.foreground = foreground;
1303 values.background = background;
1304 values.font = _titleFont->fid;
1305 values.graphics_exposures = False;
1307 _fontGC = XtGetGC (_base, valuemask, &values);
1312 void _XsMotifTitle::_configure (XEvent *event)
1314 XConfigureEvent *ce = (XConfigureEvent*)event;
1317 Check if window has been resized. If so, generate an expose event
1318 to redraw its contents.
1321 if ((_lastW != ce->width) || (_lastH != ce->height))
1323 if ((_base != 0) && XtIsManaged (_base))
1324 XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
1327 _lastH = ce->height;
1331 // _configureEventHandler
1333 void _XsMotifTitle::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
1335 if (event->type == ConfigureNotify)
1337 _XsMotifTitle *obj = (_XsMotifTitle*)clientData;
1338 obj->_configure (event);
1343 ----------------------------------------------------------------------------
1347 XtResource _XsMotifIcon::_resourceList[] = {
1353 XtOffset (_XsMotifIcon*, _iconSize),
1355 (XtPointer)IconSize_
1362 XtOffset (_XsMotifIcon*, _iconName),
1370 sizeof (XFontStruct*),
1371 XtOffset (_XsMotifIcon*, _iconFont),
1373 "-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-iso8859-1"
1380 XtOffset (_XsMotifIcon*, _iconX),
1389 XtOffset (_XsMotifIcon*, _iconY),
1397 _XsMotifIcon::_XsMotifIcon (const char *name, XsMotifWindow *win, Widget parent) :
1398 _XsMotifComponent (name, win, parent)
1408 _freePixmap = False;
1410 _width = _height = 0;
1415 _getResources (_resourceList, XtNumber (_resourceList));
1417 // Copy icon name to local memory
1421 char *tmp = new char[strlen (_iconName) + 1];
1422 strcpy (tmp, _iconName);
1426 // Configure the icon
1428 XtVaSetValues (_base, XmNwidth, _iconSize, XmNheight, _iconSize, NULL);
1433 _XsMotifIcon::~_XsMotifIcon ( )
1436 XtReleaseGC (_base, _fontGC);
1439 XtReleaseGC (_base, _pixmapGC);
1442 XFreePixmap (XtDisplay (_base), _pixmap);
1444 delete [] _iconName;
1449 void _XsMotifIcon::show ( )
1453 Configure the icon position. Either use the position specified
1454 in the resource, or place the icon at the top-left corner of the
1458 if (_placed == False)
1464 XtVaGetValues (_win->base ( ), XmNx, &x, NULL);
1473 XtVaGetValues (_win->base ( ), XmNy, &y, NULL);
1480 XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
1485 // Call the base class
1487 _XsMotifComponent::show ( );
1492 void _XsMotifIcon::setIconName (const char *iconName)
1494 assert (iconName != 0);
1496 delete [] _iconName;
1498 _iconName = new char[strlen (iconName) + 1];
1499 strcpy (_iconName, iconName);
1504 void _XsMotifIcon::setPixmap (Pixmap pixmap)
1506 assert (pixmap != 0);
1508 // Free the existing pixmap (if necessary)
1512 XFreePixmap (XtDisplay (_base), _pixmap);
1513 _freePixmap = False;
1516 // Save the new pixmap
1520 // Get the pixmap width and height
1524 unsigned int uw, uh, ub, ud;
1526 XGetGeometry (XtDisplay (_base), _pixmap, &dummy, &xd, &yd, &uw, &uh, &ub, &ud);
1534 const char *_XsMotifIcon::className ( ) const
1536 return ("_XsMotifIcon");
1539 // _componentDestroyed
1541 void _XsMotifIcon::_componentDestroyed ( )
1547 XtReleaseGC (_base, _fontGC);
1550 XtReleaseGC (_base, _pixmapGC);
1553 XFreePixmap (XtDisplay (_base), _pixmap);
1559 // Call the base-class
1561 _XsMotifComponent::_componentDestroyed ( );
1566 void _XsMotifIcon::_input (XEvent *event)
1568 static Time lastTime = (Time)0;
1570 switch (event->type)
1574 switch (event->xbutton.button)
1581 XsMoveOutline move (_base);
1585 if (move.go ( ) != False)
1588 // Relocate the window
1590 _win->setPosition (move.x ( ), move.y ( ));
1596 _win->popupMenu ( );
1604 switch (event->xbutton.button)
1609 // Get double-click time
1611 int multiClick = XtGetMultiClickTime (XtDisplay (_base));
1613 // Check for double-click
1615 if ((event->xbutton.time - lastTime) <= multiClick)
1619 lastTime = event->xbutton.time;
1629 XsMoveOutline move (_base);
1633 if (move.go ( ) != False)
1636 // Relocate the icon
1638 _win->setPosition (move.x ( ), move.y ( ));
1647 void _XsMotifIcon::_expose (XEvent *)
1649 Dimension iconHeight;
1650 Dimension iconWidth;
1652 // Compute icon size
1654 XtVaGetValues (_base, XmNwidth, &iconWidth, XmNheight, &iconHeight, NULL);
1658 _drawShadows (0, 0, iconWidth, iconHeight, 2);
1660 // Figure out the icon string
1662 const char *iconName = (_iconName != 0) ? _iconName : (_win->title ( ) != 0) ?
1663 _win->title ( ) : _win->name ( );
1665 const int fontX = 3;
1666 const int fontY = 3;
1668 if ((iconName != 0) && (iconName[0] != '\0'))
1671 int len = strlen (iconName);
1673 // Compute the text size
1675 textWidth = XTextWidth (_iconFont, iconName, len);
1677 // Center the text in the bottom of the icon (or left-justify it)
1681 if (textWidth <= (iconWidth - (fontX * 2)))
1682 x = (iconWidth - (int)textWidth) / 2;
1686 y = (int)iconHeight - _iconFont->descent - fontY;
1690 XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
1691 x, y, iconName, len);
1694 // Compute label size
1696 int labelHeight = _iconFont->descent + _iconFont->ascent + (fontY * 2);
1698 if (labelHeight >= (iconHeight - 6))
1701 // Draw the separator
1703 int sepY = (iconHeight) - labelHeight;
1705 _drawLine (1, sepY, iconWidth - 2, sepY, _bottomShadowGC);
1706 _drawLine (1, sepY + 1, iconWidth - 2, sepY + 1, _topShadowGC);
1708 // Draw the pixmap frame
1710 const int frameX = 4;
1711 const int frameY = 4;
1713 if ((frameX + 6) >= sepY)
1716 int frameWidth = iconWidth - (frameX * 2);
1717 int frameHeight = sepY - frameY - 2;
1719 _drawShadows (frameX, frameY, frameWidth, frameHeight, 1, True);
1724 _drawShadows (frameX + 1, frameY + 1, frameWidth, frameHeight, 1);
1733 if ((frameWidth > 0) && (frameHeight > 0))
1738 // Center the pixmap or top-left orient it
1740 if (frameWidth > _width)
1742 origX = (frameWidth - _width) / 2;
1743 origX += frameX + 2;
1752 if (frameHeight > _height)
1754 origY = (frameHeight - _height) / 2;
1755 origY += frameY + 2;
1761 drawH = frameHeight;
1764 XCopyArea (XtDisplay (_base), _pixmap, XtWindow (_base), _pixmapGC,
1765 0, 0, drawW, drawH, origX, origY);
1772 void _XsMotifIcon::_map ( )
1774 unsigned long valuemask;
1780 // Call the base-class
1782 _XsMotifComponent::_map ( );
1784 // Get the icon pixels
1786 XtVaGetValues (_win->base ( ), XmNdepth, &depth, XmNbackground, &bg,
1787 XmNforeground, &fg, NULL);
1789 // Create the default icon pixmap
1793 _pixmap = XCreatePixmapFromBitmapData (XtDisplay (_base), XtWindow (_base),
1794 xs_motif_icon_bits, xs_motif_icon_width, xs_motif_icon_height,
1799 setPixmap (_pixmap);
1803 // Create the icon pixmap graphics context
1805 valuemask = GCGraphicsExposures | GCForeground | GCBackground;
1807 values.graphics_exposures = False;
1808 values.foreground = fg;
1809 values.background = bg;
1811 _pixmapGC = XtGetGC (_base, valuemask, &values);
1814 // Create the font graphics context
1816 valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
1818 values.foreground = fg;
1819 values.background = bg;
1820 values.font = _iconFont->fid;
1821 values.graphics_exposures = False;
1823 _fontGC = XtGetGC (_base, valuemask, &values);
1827 ----------------------------------------------------------------------------
1831 // Static definitions
1833 int _XsMotifMenu::_count = 0;
1834 Cursor _XsMotifMenu::_cursor = None;
1835 Pixmap _XsMotifMenu::_stipple = None;
1836 Display *_XsMotifMenu::_dpy = 0;
1840 XtResource _XsMotifMenu::_resourceList[] = {
1846 XtOffset (_XsMotifMenu*, _saveUnder),
1855 XtOffset (_XsMotifMenu*, _strings[Restore]),
1864 XtOffset (_XsMotifMenu*, _strings[Move]),
1873 XtOffset (_XsMotifMenu*, _strings[Size]),
1882 XtOffset (_XsMotifMenu*, _strings[Minimize]),
1891 XtOffset (_XsMotifMenu*, _strings[Maximize]),
1900 XtOffset (_XsMotifMenu*, _strings[Raise]),
1909 XtOffset (_XsMotifMenu*, _strings[Lower]),
1918 XtOffset (_XsMotifMenu*, _strings[Close]),
1926 sizeof (XFontStruct*),
1927 XtOffset (_XsMotifMenu*, _menuFont),
1929 "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
1935 _XsMotifMenu::_XsMotifMenu (const char *name, XsMotifWindow *win) :
1936 _XsMotifBase (name, win)
1939 // Create the cursor (if necessary)
1944 // Create the menu cursor
1946 _cursor = XCreateFontCursor (XtDisplay (win->base ( )), XC_arrow);
1948 // Create a stippled pixmap
1950 Widget parent = _win->base ( );
1955 XtVaGetValues (parent, XmNforeground, &foreground, XmNbackground,
1956 &background, XmNdepth, &depth, NULL);
1958 const int pixmapWidth = 2;
1959 const int pixmapHeight = 2;
1960 static unsigned char pixmapBits[] = { 0x02, 0x01 };
1962 _dpy = XtDisplay (parent);
1963 _stipple = XCreatePixmapFromBitmapData (_dpy, DefaultRootWindow (_dpy),
1964 (char*)pixmapBits, pixmapWidth, pixmapHeight, foreground, background,
1974 // Create the component (why doesn't overrideShell work?)
1976 _base = XtVaCreatePopupShell (_name, topLevelShellWidgetClass,
1977 XtParent (_win->base ( )), XmNoverrideRedirect, True,
1978 XmNborderWidth, 1, NULL);
1980 // Install destroy handler
1982 _installDestroyHandler ( );
1984 // Install event handler ('cause we never call _XsMotifBase::show)
1986 XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
1990 _getResources (_resourceList, XtNumber (_resourceList));
1992 // Get the background color
1996 XtVaGetValues (_win->base ( ), XmNbackground, &bg, NULL);
1998 // Compute the size of the (largest) menu item
2000 int textHeight = _menuFont->ascent + _menuFont->descent;
2004 for (int loop = 0; loop < Num; loop++)
2006 tmp = XTextWidth (_menuFont, _strings[loop], strlen (_strings[loop]));
2008 if (tmp > textWidth)
2012 // Put a border around the buttons
2014 textWidth += (2 * HorizTextOffset);
2015 textHeight += (2 * VertTextOffset);
2018 The menu height is the menu-shadow (1 pixel on top and bottom) + the
2022 int menuHeight = (2 * ShadowThickness) + // Top and bottom shadow
2023 (textHeight * Num); // The menu items
2026 The menu width is the menu-shadow (1 pixel on the left and right) +
2027 the largest menu text (calculated above)
2030 int menuWidth = (2 * ShadowThickness) + // Left and right shadow
2031 textWidth; // Largest text item
2033 // Configure the popup
2035 XtVaSetValues (_base, XmNsaveUnder, _saveUnder, XmNwidth, menuWidth,
2036 XmNheight, menuHeight, NULL);
2041 _XsMotifMenu::~_XsMotifMenu ( )
2044 XtReleaseGC (_base, _fontGC);
2047 XtReleaseGC (_base, _grayGC);
2050 XtReleaseGC (_base, _backgroundGC);
2052 // Free the pixmap (if necessary)
2055 XFreePixmap (_dpy, _stipple);
2060 void _XsMotifMenu::popup (Boolean atPointer)
2062 assert (_base != 0);
2066 // Compute the location of the menu.
2075 // Menu at pointer location
2077 XQueryPointer (XtDisplay (_base), XtWindow (XtParent (_base)),
2078 &win, &win, &rootX, &rootY, &winX, &winY, &mask);
2080 x = (Position)rootX;
2081 y = (Position)rootY;
2086 // Menu at top-left corner of client area
2088 XtTranslateCoords (_win->clientArea ( ), 0, 0, &x, &y);
2093 XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
2095 // Initialize the item
2101 XtPopup (_base, XtGrabNone);
2105 if (_grabPointer ( ) == FALSE)
2112 // Pop the menu down
2116 // Ungrab the pointer
2120 if (_curItem != NoItem)
2124 Post a work-proc to process this item. This will allow everything
2125 to get caught up before we process the menu item
2128 XtAppContext appContext = XtWidgetToApplicationContext (_base);
2129 XtAppAddWorkProc (appContext, _workProc, (XtPointer)this);
2135 const char *_XsMotifMenu::className ( ) const
2137 return ("_XsMotifMenu");
2140 // _componentDestroyed
2142 void _XsMotifMenu::_componentDestroyed ( )
2148 XtReleaseGC (_base, _fontGC);
2151 XtReleaseGC (_base, _grayGC);
2154 XtReleaseGC (_base, _backgroundGC);
2160 // Call the base-class
2162 _XsMotifBase::_componentDestroyed ( );
2167 void _XsMotifMenu::_processEvents ( )
2169 assert (_base != 0);
2171 XtAppContext appContext = XtWidgetToApplicationContext (_base);
2173 Display *dpy = XtDisplay (_base);
2178 XtAppNextEvent (appContext, &event);
2180 // Process this event
2198 // Process only the last motion event
2200 while (XPending (dpy) > 0)
2202 XPeekEvent (dpy, &next);
2203 if (next.type != MotionNotify)
2205 XtAppNextEvent (appContext, &event);
2208 // Track the mouse and toggle the menu items
2210 Item item = _trackPointer ((XMotionEvent*)&event);
2212 // Unselect the current item (if the item is different)
2214 if (item != _curItem)
2216 _toggleItem (_curItem, False);
2218 // Select the new item
2220 _toggleItem ((_curItem = item), True);
2227 XtDispatchEvent (&event);
2236 void _XsMotifMenu::_processItem (Item item)
2250 Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
2252 // Warp the pointer to the center of the window
2254 Dimension width, height;
2255 XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
2257 XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
2258 (width / 2), (height / 2));
2262 XsMoveOutline move (base);
2266 if (move.go (True) != False)
2269 // Relocate the window
2271 _win->setPosition (move.x ( ), move.y ( ));
2277 Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
2279 // Warp the pointer to the center of the window
2281 Dimension width, height;
2282 XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
2284 XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
2285 (width / 2), (height / 2));
2287 // Resize the window
2289 XsResizeOutline resize (_win->base ( ), XsResizeOutline::Undetermined);
2290 resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
2294 if (resize.go (True) != False)
2297 // Relocate the window
2299 _win->setPosition (resize.x ( ), resize.y ( ));
2300 _win->setSize (resize.width ( ), resize.height ( ));
2336 void _XsMotifMenu::_redrawMenu ( )
2340 // Get the size of the menu
2342 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
2344 // Draw a shadow around the menu
2346 _drawShadows (0, 0, w, h, ShadowThickness);
2348 // Cycle and draw all of the elements
2350 for (int loop = 0; loop < Num; loop++)
2351 _redrawItem ((Item)loop);
2356 void _XsMotifMenu::_redrawItem (Item item)
2361 int x = ShadowThickness + HorizTextOffset;
2365 Compute the y-position of the element. This will be the size of the
2366 top-shadow + the items before it + the offset of the item itself
2369 y = ShadowThickness + // Top shadow
2370 (item * ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent))) +
2371 (VertTextOffset + _menuFont->ascent); // The item iteself
2373 // Figure out the graphics-context
2377 if (_win->minimized ( ))
2378 gc = ((item == Size) || (item == Minimize)) ? _grayGC : _fontGC;
2379 else if (_win->maximized ( ))
2380 gc = (item == Maximize) ? _grayGC : _fontGC;
2382 gc = (item == Restore) ? _grayGC : _fontGC;
2386 XDrawString (XtDisplay (_base), XtWindow (_base), gc, x, y,
2387 _strings[item], strlen (_strings[item]));
2392 void _XsMotifMenu::_toggleItem (Item item, Boolean active)
2398 Either draw the background of the specified item in the active color
2399 or the standard background color
2402 GC gc = (active) ? _topShadowGC : _backgroundGC;
2404 // Get the width of the menu
2406 Dimension menuWidth;
2407 XtVaGetValues (_base, XmNwidth, &menuWidth, NULL);
2409 // Compute the location and size of the rectangle
2412 unsigned int width, height;
2414 x = ShadowThickness;
2415 height = ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent));
2416 y = ShadowThickness + (item * height);
2417 width = menuWidth - (2 * ShadowThickness);
2419 // Draw the filled rectangle
2421 XFillRectangle (XtDisplay (_base), XtWindow (_base), gc, x, y, width, height);
2430 _XsMotifMenu::Item _XsMotifMenu::_trackPointer (XMotionEvent *event)
2432 assert (_base != 0);
2434 Dimension menuWidth;
2435 Dimension menuHeight;
2438 // Get the menu size and position
2440 XtVaGetValues (_base, XmNwidth, &menuWidth, XmNheight, &menuHeight,
2441 XmNx, &x, XmNy, &y, NULL);
2443 // Make sure the pointer is in the menu
2445 if ((event->x_root < x) || (event->x_root > (x + menuWidth)))
2448 if ((event->y_root < y) || (event->y_root > (y + menuHeight)))
2451 // Make sure the pointer is on the confines of the shadow
2453 if ((event->x < ShadowThickness) || (event->x > (menuWidth - (2 * ShadowThickness))))
2456 if ((event->y < ShadowThickness) || (event->y > (menuHeight - (2 * ShadowThickness))))
2460 Now we are just concerned with the y-position. Subtract off the
2461 shadow thickness to normalize the location
2464 int yPos = event->y - ShadowThickness;
2466 // Compute which item the mouse is in
2468 int itemHeight = (VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent);
2470 Item item = (Item)(yPos / itemHeight);
2472 // Validate that the item is not grayed-out
2474 if (_win->minimized ( ))
2476 if ((item == Size) || (item == Minimize))
2479 else if (_win->maximized ( ))
2481 if (item == Maximize)
2484 else if (item == Restore)
2492 Boolean _XsMotifMenu::_grabPointer ( )
2495 // Sync everything up before being grabby
2497 XSync (XtDisplay (_base), False);
2501 if (XGrabPointer (XtDisplay (_base), XtWindow (_base), False,
2502 (unsigned int)(ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
2503 EnterWindowMask | LeaveWindowMask), GrabModeAsync,
2504 GrabModeAsync, None, _cursor, CurrentTime) != GrabSuccess)
2506 XBell (XtDisplay (_base), 100);
2515 void _XsMotifMenu::_ungrabPointer ( )
2518 // Ungrab the pointer
2520 XUngrabPointer (XtDisplay (_base), CurrentTime);
2522 // Sync everything back up
2524 XSync (XtDisplay (_base), False);
2529 void _XsMotifMenu::_map ( )
2532 // Call the base-class
2534 _XsMotifBase::_map ( );
2536 unsigned long valuemask;
2543 XtVaGetValues (XtParent (_base), XmNforeground, &foreground, NULL);
2544 XtVaGetValues (_base, XmNbackground, &background, NULL);
2546 // Create the font graphics context
2548 valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
2550 values.foreground = foreground;
2551 values.background = background;
2552 values.font = _menuFont->fid;
2553 values.graphics_exposures = False;
2555 _fontGC = XtGetGC (_base, valuemask, &values);
2557 // Create the insensitive font graphics context
2559 valuemask |= (GCFillStyle | GCTile);
2561 values.fill_style = FillTiled;
2562 values.tile = _stipple;
2564 _grayGC = XtGetGC (_base, valuemask, &values);
2566 // Create the background contexts
2568 valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
2569 values.line_width = 0;
2570 values.graphics_exposures = False;
2571 values.foreground = background;
2573 _backgroundGC = XtGetGC (_base, valuemask, &values);
2578 Boolean _XsMotifMenu::_workProc (XtPointer clientData)
2580 _XsMotifMenu *obj = (_XsMotifMenu*)clientData;
2581 if (obj->_curItem != NoItem)
2582 obj->_processItem (obj->_curItem);
2588 ----------------------------------------------------------------------------
2592 // Static definitions
2594 XtResource XsMotifWindow::_resourceList[] = {
2600 XtOffset (XsMotifWindow*, _showBorder),
2609 XtOffset (XsMotifWindow*, _showResize),
2618 XtOffset (XsMotifWindow*, _showTitle),
2627 XtOffset (XsMotifWindow*, _showMenu),
2636 XtOffset (XsMotifWindow*, _showMinimize),
2645 XtOffset (XsMotifWindow*, _showMaximize),
2654 XtOffset (XsMotifWindow*, _lowerOnIconify),
2663 XtOffset (XsMotifWindow*, _minW),
2665 (XtPointer)((BorderSize_ + ButtonSize_) * 3)
2672 XtOffset (XsMotifWindow*, _maxW),
2681 XtOffset (XsMotifWindow*, _minH),
2683 (XtPointer)((BorderSize_ + ButtonSize_) * 3)
2690 XtOffset (XsMotifWindow*, _maxH),
2698 XsMotifWindow::XsMotifWindow (const char *name) : XsMDIWindow (name)
2704 for (loop = 0; loop < _XsMotifSide::Max; loop++)
2710 for (loop = 0; loop < _XsMotifButton::Max; loop++)
2723 XsMotifWindow::~XsMotifWindow ( )
2727 for (loop = 0; loop < _XsMotifSide::Max; loop++)
2729 delete _corners[loop];
2730 delete _sides[loop];
2733 for (loop = 0; loop < _XsMotifButton::Max; loop++)
2734 delete _buttons[loop];
2743 void XsMotifWindow::raise ( )
2745 Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2747 XRaiseWindow (XtDisplay (w), XtWindow (w));
2752 void XsMotifWindow::lower ( )
2754 Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2756 XLowerWindow (XtDisplay (w), XtWindow (w));
2761 void XsMotifWindow::minimize ( )
2763 assert (_base != 0);
2765 // Check if we are already minimized
2767 if (_minimized == True)
2770 // Minimize the window
2776 // Lower (if necessary)
2778 if (_lowerOnIconify)
2786 void XsMotifWindow::maximize ( )
2788 assert (_base != 0);
2790 // Check if we are already in this state
2792 if (_maximized == True)
2795 // Restore (if necessary)
2800 // Save current dimensions
2802 XtVaGetValues (_base, XmNx, &_savedX, XmNy, &_savedY, XmNwidth,
2803 &_savedWidth, XmNheight, &_savedHeight, NULL);
2806 Constrain the new window size. The size of the maximized window
2807 is equal to the size of the current clip-window of the canvas.
2810 const Dimension offset = 5; // Border around max'd window
2812 Widget clipWindow = XtParent (XtParent (_base));
2813 assert (clipWindow != 0);
2814 Dimension clipW, clipH;
2818 XtVaGetValues (clipWindow, XmNheight, &clipH, XmNwidth, &clipW, NULL);
2822 if (clipW > (offset * 2))
2823 clipW -= (offset * 2);
2825 if (clipH > (offset * 2))
2826 clipH -= (offset * 2);
2828 // Compute the new window position (map clip-window to work-area)
2830 XTranslateCoordinates (XtDisplay (_base), XtWindow (clipWindow),
2831 XtWindow (XtParent (_base)), (int)offset, (int)offset,
2832 &newX, &newY, &child);
2834 // Set new maximum dimensions
2836 setPosition ((Position)newX, (Position)newY);
2837 setSize (clipW, clipH);
2841 // Redraw the maximize button
2843 _buttons[_XsMotifButton::Maximize]->redraw ( );
2848 void XsMotifWindow::restore ( )
2850 assert (_base != 0);
2852 // Check if we are already restored
2854 if ((_maximized == False) && (_minimized == False))
2857 // Either un-minimize or un-maximize
2862 // Restore the window
2867 // If maximized, restore again
2879 // Restore saved dimensions
2881 setPosition (_savedX, _savedY);
2882 setSize (_savedWidth, _savedHeight);
2888 void XsMotifWindow::close ( )
2892 Don't delete the window (because its not ours to delete).
2904 void XsMotifWindow::setTitle (const char *title)
2907 _title->setTitle (title);
2912 void XsMotifWindow::setIconName (const char *iconName)
2915 _icon->setIconName (iconName);
2920 void XsMotifWindow::setPixmap (Pixmap pixmap)
2923 _icon->setPixmap (pixmap);
2928 void XsMotifWindow::popupMenu (Boolean b)
2936 void XsMotifWindow::setPosition (Position x, Position y)
2940 Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2942 XtVaSetValues (w, XmNx, x, XmNy, y, NULL);
2945 XsMDIWindow::setPosition (x, y); // Cache the points
2950 void XsMotifWindow::setSize (Dimension w, Dimension h)
2953 // Set the window size
2959 else if ((_maxW != (Dimension)-1) && (w > _maxW))
2964 else if ((_maxH != (Dimension)-1) && (h > _maxH))
2967 if (_minimized == False)
2968 XtVaSetValues (_base, XmNwidth, w, XmNheight, h, NULL);
2970 // If window was maximized, change the window state back to normal
2972 if (_maximized == True)
2976 // Redraw the maximize button
2978 _buttons[_XsMotifButton::Maximize]->redraw ( );
2982 XsMDIWindow::setSize (w, h); // Cache the points
2987 const char* XsMotifWindow::className ( ) const
2989 return ("XsMotifWindow");
2994 void XsMotifWindow::_createWindow (Widget parent)
2996 assert (parent != 0);
2998 // Create the window frame
3000 _base = XtVaCreateWidget (_name, xmFormWidgetClass, parent,
3001 XmNborderWidth, (Dimension)1, NULL);
3003 // Install destroy handler
3005 _installDestroyHandler ( );
3009 _getResources (_resourceList, XtNumber (_resourceList));
3012 Fix configuration inter-dependencies. Here are the rules:
3014 1) If there is no border, then there are no resize handles
3015 2) If there is no title, then there are no buttons (would look stupid)
3018 if (_showBorder == False)
3019 _showResize = False;
3021 if (_showTitle == False)
3024 _showMinimize = False;
3025 _showMaximize = False;
3037 _corners[_XsMotifCorner::TopLeft] = new _XsMotifCorner ("topLeft", this, _XsMotifCorner::TopLeft);
3039 XtVaSetValues (_corners[_XsMotifCorner::TopLeft]->base ( ), XmNtopAttachment,
3040 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
3041 XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3045 _corners[_XsMotifCorner::TopRight] = new _XsMotifCorner ("topRight", this, _XsMotifCorner::TopRight);
3047 XtVaSetValues (_corners[_XsMotifCorner::TopRight]->base ( ), XmNtopAttachment,
3048 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
3049 XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3053 _corners[_XsMotifCorner::BottomLeft] = new _XsMotifCorner ("bottomLeft", this, _XsMotifCorner::BottomLeft);
3055 XtVaSetValues (_corners[_XsMotifCorner::BottomLeft]->base ( ), XmNtopAttachment,
3056 XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
3057 XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3061 _corners[_XsMotifCorner::BottomRight] = new _XsMotifCorner ("bottomRight", this, _XsMotifCorner::BottomRight);
3063 XtVaSetValues (_corners[_XsMotifCorner::BottomRight]->base ( ), XmNtopAttachment,
3064 XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
3065 XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3077 _sides[_XsMotifSide::Top] = new _XsMotifSide ("top", this, _XsMotifSide::Top);
3079 XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNtopAttachment,
3080 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, NULL);
3084 XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNleftAttachment,
3085 XmATTACH_WIDGET, XmNleftWidget, _corners[_XsMotifCorner::TopLeft]->base ( ),
3086 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3087 _corners[_XsMotifCorner::TopRight]->base ( ), NULL);
3091 XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNleftAttachment,
3092 XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3097 _sides[_XsMotifSide::Bottom] = new _XsMotifSide ("bottom", this, _XsMotifSide::Bottom);
3099 XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNtopAttachment,
3100 XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, NULL);
3104 XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNleftAttachment,
3105 XmATTACH_WIDGET, XmNleftWidget, _corners[_XsMotifCorner::BottomLeft]->base ( ),
3106 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3107 _corners[_XsMotifCorner::BottomRight]->base ( ), NULL);
3111 XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNleftAttachment,
3112 XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3117 _sides[_XsMotifSide::Left] = new _XsMotifSide ("left", this, _XsMotifSide::Left);
3119 XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNleftAttachment,
3120 XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3124 XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNtopAttachment,
3125 XmATTACH_WIDGET, XmNtopWidget, _corners[_XsMotifCorner::TopLeft]->base ( ),
3126 XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
3127 _corners[_XsMotifCorner::BottomLeft]->base ( ), NULL);
3131 XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNtopAttachment,
3132 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
3137 _sides[_XsMotifSide::Right] = new _XsMotifSide ("right", this, _XsMotifSide::Right);
3139 XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNleftAttachment,
3140 XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3144 XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNtopAttachment,
3145 XmATTACH_WIDGET, XmNtopWidget, _corners[_XsMotifCorner::TopRight]->base ( ),
3146 XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
3147 _corners[_XsMotifCorner::BottomRight]->base ( ), NULL);
3151 XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNtopAttachment,
3152 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
3160 _buttons[_XsMotifButton::Menu] = new _XsMotifButton ("menu", this, _XsMotifButton::Menu);
3162 XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNbottomAttachment,
3163 XmATTACH_NONE, XmNrightAttachment, XmATTACH_NONE, NULL);
3167 XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
3168 XmATTACH_WIDGET, XmNleftWidget, _sides[_XsMotifSide::Left]->base ( ),
3169 XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3174 XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
3175 XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, NULL);
3183 _buttons[_XsMotifButton::Maximize] = new _XsMotifButton ("maximize", this, _XsMotifButton::Maximize);
3185 XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNbottomAttachment,
3186 XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE, NULL);
3190 XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
3191 XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3192 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
3197 XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
3198 XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3206 _buttons[_XsMotifButton::Minimize] = new _XsMotifButton ("minimize", this, _XsMotifButton::Minimize);
3208 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3209 XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE,
3214 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ), XmNtopAttachment,
3215 XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3216 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3217 _sides[_XsMotifSide::Right]->base ( ), NULL);
3221 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3222 XmNtopAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
3228 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3229 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3230 _buttons[_XsMotifButton::Maximize]->base ( ), NULL);
3240 _title = new _XsMotifTitle ("title", this);
3242 XtVaSetValues (_title->base ( ), XmNbottomAttachment, XmATTACH_NONE,
3247 XtVaSetValues (_title->base ( ), XmNtopAttachment, XmATTACH_WIDGET,
3248 XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3249 XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget,
3250 _sides[_XsMotifSide::Left]->base ( ), XmNrightAttachment,
3251 XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
3256 XtVaSetValues (_title->base ( ), XmNtopAttachment, XmATTACH_FORM,
3257 XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
3263 XtVaSetValues (_title->base ( ), XmNleftAttachment, XmATTACH_WIDGET,
3264 XmNleftWidget, _buttons[_XsMotifButton::Menu]->base ( ), NULL);
3267 Widget ba = (_buttons[_XsMotifButton::Minimize] != 0) ?
3268 _buttons[_XsMotifButton::Minimize]->base ( ) :
3269 (_buttons[_XsMotifButton::Maximize] != 0) ?
3270 _buttons[_XsMotifButton::Maximize]->base ( ) : 0;
3274 XtVaSetValues (_title->base ( ), XmNrightAttachment, XmATTACH_WIDGET,
3275 XmNrightWidget, ba, NULL);
3283 _icon = new _XsMotifIcon ("icon", this, parent);
3289 _menu = new _XsMotifMenu ("menu", this);
3295 _clientArea = XtVaCreateWidget ("clientArea", xmFormWidgetClass, _base, NULL);
3299 XtVaSetValues (_clientArea, XmNleftAttachment, XmATTACH_WIDGET,
3300 XmNleftWidget, _sides[_XsMotifSide::Left]->base ( ), XmNrightAttachment,
3301 XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
3302 XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
3303 _sides[_XsMotifSide::Bottom]->base ( ), NULL);
3307 XtVaSetValues (_clientArea, XmNleftAttachment, XmATTACH_FORM,
3308 XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM,
3312 Widget topW = (_showTitle) ? _title->base ( ) :
3313 (_showBorder) ? _sides[_XsMotifSide::Top]->base ( ) : 0;
3317 XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_WIDGET,
3318 XmNtopWidget, topW, NULL);
3321 XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_FORM, NULL);
3323 // Call the class function to create the contents of the window
3325 _buildClientArea (_clientArea);
3327 // Add an event handler to be called when this window is mapped
3329 XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
3335 for (loop = 0; loop < _XsMotifSide::Max; loop++)
3337 if (_corners[loop] != 0)
3338 _corners[loop]->show ( );
3339 if (_sides[loop] != 0)
3340 _sides[loop]->show ( );
3343 for (loop = 0; loop < _XsMotifButton::Max; loop++)
3345 if (_buttons[loop] != 0)
3346 _buttons[loop]->show ( );
3355 void XsMotifWindow::_mapEvent ( )
3358 // Raise the client-area
3360 XRaiseWindow (XtDisplay (_clientArea), XtWindow (_clientArea));
3365 void XsMotifWindow::_mapEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
3367 if (event->type == MapNotify)
3369 XsMotifWindow *obj = (XsMotifWindow*)clientData;
3371 XtRemoveEventHandler (obj->_base, StructureNotifyMask, False, obj->_mapEventHandler, clientData);