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 if (_topShadowGC == 0) // JACS
381 // Get the size of the corner
383 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
387 _drawShadows (0, 0, w, h, 1);
389 // Draw the extra lines and relief
395 _drawLine (1, 1, w - 2, 1, _topShadowGC);
396 _drawLine (1, 1, 1, h - 2, _topShadowGC);
400 _drawLine (_borderSize - 1, _borderSize - 1, _borderSize +
401 _buttonSize - 2, _borderSize - 1, _bottomShadowGC);
403 _drawLine (_borderSize - 1, _borderSize - 1, _borderSize - 1,
404 _borderSize + _buttonSize - 2, _bottomShadowGC);
410 _drawLine (1, 1, w - 2, 1, _topShadowGC);
411 _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
415 _drawLine (0, _borderSize - 1, _buttonSize - 1, _borderSize - 1,
418 _drawLine (w - _borderSize, _borderSize - 1, w - _borderSize,
419 _borderSize + _buttonSize - 2, _topShadowGC);
425 _drawLine (1, 1, 1, h - 2, _topShadowGC);
426 _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
430 _drawLine (_borderSize - 1, h - _borderSize, _borderSize +
431 _buttonSize - 2, h - _borderSize, _topShadowGC);
433 _drawLine (_borderSize - 1, 1, _borderSize - 1,
434 _buttonSize - 1, _bottomShadowGC);
440 _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
441 _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
445 _drawLine (1, h - _borderSize, _buttonSize, h - _borderSize,
448 _drawLine (w - _borderSize, 1, w - _borderSize,
449 _buttonSize - 1, _topShadowGC);
460 void _XsMotifCorner::_input (XEvent *event)
466 if (event->xbutton.button == 2)
468 XsMoveOutline move (_win->base ( ));
472 if (move.go ( ) != False)
475 // Relocate the window
477 _win->setPosition (move.x ( ), move.y ( ));
480 else if (event->xbutton.button == 3)
487 switch (event->xbutton.button)
492 _win->raise ( ); // Raise the window
501 // Figure kind of resize we are doing
505 if (_corner == TopLeft)
506 dir = XsResizeOutline::Up | XsResizeOutline::Left;
507 else if (_corner == TopRight)
508 dir = XsResizeOutline::Up | XsResizeOutline::Right;
509 else if (_corner == BottomLeft)
510 dir = XsResizeOutline::Down | XsResizeOutline::Left;
511 else if (_corner == BottomRight)
512 dir = XsResizeOutline::Down | XsResizeOutline::Right;
516 XsResizeOutline resize (_win->base ( ), dir);
517 resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
521 if (resize.go ( ) != False)
524 // Relocate the window
526 _win->setPosition (resize.x ( ), resize.y ( ));
527 _win->setSize (resize.width ( ), resize.height ( ));
536 void _XsMotifCorner::_map ( )
539 // Call the base-class
541 _XsMotifComponent::_map ( );
543 // Install the cursor
545 if (_corner == TopLeft)
546 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopLeftCursor]);
547 else if (_corner == TopRight)
548 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopRightCursor]);
549 else if (_corner == BottomLeft)
550 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomLeftCursor]);
551 else if (_corner == BottomRight)
552 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomRightCursor]);
558 ----------------------------------------------------------------------------
564 _XsMotifSide::_XsMotifSide (const char *name, XsMotifWindow *win, Side side) :
565 _XsMotifComponent (name, win)
571 _lastW = _lastH = -1;
573 // Configure component
580 XtVaSetValues (_base, XmNheight, _borderSize, XmNborderWidth,
587 XtVaSetValues (_base, XmNwidth, _borderSize, XmNborderWidth,
595 // Install event handler
597 XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
602 _XsMotifSide::~_XsMotifSide ( )
609 const char *_XsMotifSide::className ( ) const
611 return ("_XsMotifSide");
616 void _XsMotifSide::_expose (XEvent *event)
618 if (_topShadowGC == 0) // JACS
621 // Clear out the window first
624 XClearWindow (XtDisplay (_base), XtWindow (_base));
628 // Get the size of the side
630 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
634 _drawShadows (0, 0, w, h, 1);
636 // Draw the extra lines
642 _drawLine (1, 1, w - 2, 1, _topShadowGC);
647 _drawLine (1, h - 2, w - 2, h - 2, _bottomShadowGC);
652 _drawLine (1, 1, 1, h - 2, _topShadowGC);
657 _drawLine (w - 2, 1, w - 2, h - 2, _bottomShadowGC);
667 void _XsMotifSide::_input (XEvent *event)
673 if (event->xbutton.button == 2)
675 XsMoveOutline move (_win->base ( ));
679 if (move.go ( ) != False)
682 // Relocate the window
684 _win->setPosition (move.x ( ), move.y ( ));
687 else if (event->xbutton.button == 3)
694 switch (event->xbutton.button)
699 _win->raise ( ); // Raise the window
708 // Figure kind of resize we are doing
713 dir = XsResizeOutline::Up;
714 else if (_side == Bottom)
715 dir = XsResizeOutline::Down;
716 else if (_side == Left)
717 dir = XsResizeOutline::Left;
718 else if (_side == Right)
719 dir = XsResizeOutline::Right;
723 XsResizeOutline resize (_win->base ( ), dir);
724 resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
728 if (resize.go ( ) != False)
731 // Relocate the window
733 _win->setPosition (resize.x ( ), resize.y ( ));
734 _win->setSize (resize.width ( ), resize.height ( ));
743 void _XsMotifSide::_map ( )
746 // Call the base-class
748 _XsMotifComponent::_map ( );
750 // Install the cursor
753 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[TopCursor]);
754 else if (_side == Bottom)
755 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[BottomCursor]);
756 else if (_side == Left)
757 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[LeftCursor]);
758 else if (_side == Right)
759 XDefineCursor (XtDisplay (_base), XtWindow (_base), _cursors[RightCursor]);
766 void _XsMotifSide::_configure (XEvent *event)
768 XConfigureEvent *ce = (XConfigureEvent*)event;
771 Check if window has been resized. If so, generate an expose event
772 to redraw its contents.
775 if ((_lastW != ce->width) || (_lastH != ce->height))
777 if ((_base != 0) && XtIsManaged (_base))
778 XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
785 // _configureEventHandler
787 void _XsMotifSide::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
789 if (event->type == ConfigureNotify)
791 _XsMotifSide *obj = (_XsMotifSide*)clientData;
792 obj->_configure (event);
797 ----------------------------------------------------------------------------
803 _XsMotifButton::_XsMotifButton (const char *name, XsMotifWindow *win, Button button) :
804 _XsMotifComponent (name, win)
812 // Configure the component
814 XtVaSetValues (_base, XmNheight, _buttonSize, XmNwidth, _buttonSize,
815 XmNborderWidth, (Dimension)0, NULL);
820 _XsMotifButton::~_XsMotifButton ( )
827 void _XsMotifButton::redraw ( )
830 // Make sure component is viewable
832 if (!XtIsRealized (_base))
835 // Check if window is viewable
837 XWindowAttributes attrs;
838 XGetWindowAttributes (XtDisplay (_base), XtWindow (_base), &attrs);
840 if (attrs.map_state == IsViewable)
841 _expose (0); // Just pretend we got an expose event
846 const char *_XsMotifButton::className ( ) const
848 return ("_XsMotifButton");
853 void _XsMotifButton::_expose (XEvent *event)
855 if (_topShadowGC == 0) // JACS
860 // Get the size of the button
862 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
866 _drawShadows (0, 0, w, h, 1, _pressed);
868 // Draw the extra line
870 _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
872 // Check if we need to draw the decal
874 if ((_button != Maximize) && (event == 0))
877 // Compute the decal size
880 Boolean reverse = False;
886 dw = _buttonSize - 6;
897 dw = _buttonSize - 6;
900 if (_win->maximized ( ))
911 _drawShadows ((w / 2) - (dw / 2), (h / 2) - (dh / 2), dw, dh, 1, reverse);
916 void _XsMotifButton::_input (XEvent *event)
918 static Time lastTime = (Time)0;
924 if (event->xbutton.button == 1)
931 // Get double-click time
933 int multiClick = XtGetMultiClickTime (XtDisplay (_base));
935 // Check for double-click
937 if ((event->xbutton.time - lastTime) <= multiClick)
943 lastTime = event->xbutton.time;
945 // Redraw the button (pushed-in)
951 _win->popupMenu (False);
953 // The menu will consume the ButtonRelease, so fake one
959 else if ((_button == Minimize) || (_button == Maximize))
964 else if (event->xbutton.button == 2)
966 XsMoveOutline move (_win->base ( ));
970 if (move.go ( ) != False)
973 // Relocate the window
975 _win->setPosition (move.x ( ), move.y ( ));
978 else if (event->xbutton.button == 3)
985 if (event->xbutton.button == 1)
989 // Check if pointer is really in the window
991 XButtonEvent *b = &event->xbutton;
992 Dimension width, height;
993 Boolean inWindow = False;
995 XtVaGetValues (_base, XmNwidth, &width, XmNheight, &height, NULL);
996 if ((b->x >= 0) && (b->y >= 0) && (b->x < width) && (b->y < height))
999 if (_button == Minimize)
1003 if (_win->minimized ( ))
1011 else if (_button == Maximize)
1015 if (_win->maximized ( ))
1031 void _XsMotifButton::_map ( )
1034 // Call the base-class
1036 _XsMotifComponent::_map ( );
1040 XRaiseWindow (XtDisplay (_base), XtWindow (_base));
1044 ----------------------------------------------------------------------------
1048 XtResource _XsMotifTitle::_resourceList[] = {
1054 XtOffset (_XsMotifTitle*, _titleString),
1062 sizeof (XFontStruct*),
1063 XtOffset (_XsMotifTitle*, _titleFont),
1065 "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
1071 _XsMotifTitle::_XsMotifTitle (const char *name, XsMotifWindow *win) :
1072 _XsMotifComponent (name, win)
1081 _lastW = _lastH = -1;
1085 _getResources (_resourceList, XtNumber (_resourceList));
1087 // Copy title string to local memory
1089 if (_titleString != 0)
1091 char *tmp = new char[strlen (_titleString) + 1];
1092 strcpy (tmp, _titleString);
1096 // Configure the title
1098 XtVaSetValues (_base, XmNheight, _buttonSize, XmNborderWidth,
1099 (Dimension)0, NULL);
1101 // Install event handler
1103 XtAddEventHandler (_base, StructureNotifyMask, False, _configureEventHandler, (XtPointer)this);
1108 _XsMotifTitle::~_XsMotifTitle ( )
1111 XtReleaseGC (_base, _fontGC);
1113 delete [] _titleString;
1118 void _XsMotifTitle::setTitle (const char *title)
1120 assert (title != 0);
1122 delete [] _titleString;
1124 _titleString = new char[strlen (title) + 1];
1125 strcpy (_titleString, title);
1130 const char *_XsMotifTitle::className ( ) const
1132 return ("_XsMotifTitle");
1135 // _componentDestroyed
1137 void _XsMotifTitle::_componentDestroyed ( )
1143 XtReleaseGC (_base, _fontGC);
1149 _XsMotifComponent::_componentDestroyed ( );
1154 void _XsMotifTitle::_redraw ( )
1156 _expose (0); // Just pretend we got an expose event
1161 void _XsMotifTitle::_expose (XEvent *event)
1163 if (_topShadowGC == 0) // JACS
1166 // Clear out the window first
1169 XClearWindow (XtDisplay (_base), XtWindow (_base));
1173 // Get the size of the button
1175 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
1179 _drawShadows (0, 0, w, h, 1, _pressed);
1181 // Draw the extra line
1183 _drawLine (1, h - 2, w - 2, h - 2, (_pressed) ? _topShadowGC : _bottomShadowGC);
1185 // If this is an artificial event, no need continuing
1190 // Draw the text string
1192 const int LeftOffset = 5;
1193 const int TopOffset = 2;
1195 // Figure out the title
1197 const char *title = (_titleString != 0) ? _titleString : _win->name ( );
1199 if ((title != 0) && (title[0] != '\0'))
1201 int len = strlen (title);
1203 XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
1204 LeftOffset, TopOffset + _titleFont->ascent, title, len);
1210 void _XsMotifTitle::_input (XEvent *event)
1212 switch (event->type)
1216 switch (event->xbutton.button)
1226 XsMoveOutline move (_win->base ( ));
1230 if (move.go ( ) != False)
1233 // Relocate the window
1235 _win->setPosition (move.x ( ), move.y ( ));
1241 _win->popupMenu ( );
1249 switch (event->xbutton.button)
1265 XsMoveOutline move (_win->base ( ));
1269 if (move.go ( ) != False)
1272 // Relocate the window
1274 _win->setPosition (move.x ( ), move.y ( ));
1276 // Redraw the title bar
1288 void _XsMotifTitle::_map ( )
1291 // Call the base-class
1293 _XsMotifComponent::_map ( );
1297 XRaiseWindow (XtDisplay (_base), XtWindow (_base));
1299 unsigned long valuemask;
1306 XtVaGetValues (_win->base ( ), XmNforeground, &foreground, XmNbackground, &background, NULL);
1308 // Create the font graphics context
1310 valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
1312 values.foreground = foreground;
1313 values.background = background;
1314 values.font = _titleFont->fid;
1315 values.graphics_exposures = False;
1317 _fontGC = XtGetGC (_base, valuemask, &values);
1322 void _XsMotifTitle::_configure (XEvent *event)
1324 XConfigureEvent *ce = (XConfigureEvent*)event;
1327 Check if window has been resized. If so, generate an expose event
1328 to redraw its contents.
1331 if ((_lastW != ce->width) || (_lastH != ce->height))
1333 if ((_base != 0) && XtIsManaged (_base))
1334 XClearArea (XtDisplay (_base), XtWindow (_base), 0, 0, 0, 0, True);
1337 _lastH = ce->height;
1341 // _configureEventHandler
1343 void _XsMotifTitle::_configureEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
1345 if (event->type == ConfigureNotify)
1347 _XsMotifTitle *obj = (_XsMotifTitle*)clientData;
1348 obj->_configure (event);
1353 ----------------------------------------------------------------------------
1357 XtResource _XsMotifIcon::_resourceList[] = {
1363 XtOffset (_XsMotifIcon*, _iconSize),
1365 (XtPointer)IconSize_
1372 XtOffset (_XsMotifIcon*, _iconName),
1380 sizeof (XFontStruct*),
1381 XtOffset (_XsMotifIcon*, _iconFont),
1383 "-*-helvetica-bold-r-normal-*-12-*-*-*-*-*-iso8859-1"
1390 XtOffset (_XsMotifIcon*, _iconX),
1399 XtOffset (_XsMotifIcon*, _iconY),
1407 _XsMotifIcon::_XsMotifIcon (const char *name, XsMotifWindow *win, Widget parent) :
1408 _XsMotifComponent (name, win, parent)
1418 _freePixmap = False;
1420 _width = _height = 0;
1425 _getResources (_resourceList, XtNumber (_resourceList));
1427 // Copy icon name to local memory
1431 char *tmp = new char[strlen (_iconName) + 1];
1432 strcpy (tmp, _iconName);
1436 // Configure the icon
1438 XtVaSetValues (_base, XmNwidth, _iconSize, XmNheight, _iconSize, NULL);
1443 _XsMotifIcon::~_XsMotifIcon ( )
1446 XtReleaseGC (_base, _fontGC);
1449 XtReleaseGC (_base, _pixmapGC);
1452 XFreePixmap (XtDisplay (_base), _pixmap);
1454 delete [] _iconName;
1459 void _XsMotifIcon::show ( )
1463 Configure the icon position. Either use the position specified
1464 in the resource, or place the icon at the top-left corner of the
1468 if (_placed == False)
1474 XtVaGetValues (_win->base ( ), XmNx, &x, NULL);
1483 XtVaGetValues (_win->base ( ), XmNy, &y, NULL);
1490 XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
1495 // Call the base class
1497 _XsMotifComponent::show ( );
1502 void _XsMotifIcon::setIconName (const char *iconName)
1504 assert (iconName != 0);
1506 delete [] _iconName;
1508 _iconName = new char[strlen (iconName) + 1];
1509 strcpy (_iconName, iconName);
1514 void _XsMotifIcon::setPixmap (Pixmap pixmap)
1516 assert (pixmap != 0);
1518 // Free the existing pixmap (if necessary)
1522 XFreePixmap (XtDisplay (_base), _pixmap);
1523 _freePixmap = False;
1526 // Save the new pixmap
1530 // Get the pixmap width and height
1534 unsigned int uw, uh, ub, ud;
1536 XGetGeometry (XtDisplay (_base), _pixmap, &dummy, &xd, &yd, &uw, &uh, &ub, &ud);
1544 const char *_XsMotifIcon::className ( ) const
1546 return ("_XsMotifIcon");
1549 // _componentDestroyed
1551 void _XsMotifIcon::_componentDestroyed ( )
1557 XtReleaseGC (_base, _fontGC);
1560 XtReleaseGC (_base, _pixmapGC);
1563 XFreePixmap (XtDisplay (_base), _pixmap);
1569 // Call the base-class
1571 _XsMotifComponent::_componentDestroyed ( );
1576 void _XsMotifIcon::_input (XEvent *event)
1578 static Time lastTime = (Time)0;
1580 switch (event->type)
1584 switch (event->xbutton.button)
1591 XsMoveOutline move (_base);
1595 if (move.go ( ) != False)
1598 // Relocate the window
1600 _win->setPosition (move.x ( ), move.y ( ));
1606 _win->popupMenu ( );
1614 switch (event->xbutton.button)
1619 // Get double-click time
1621 int multiClick = XtGetMultiClickTime (XtDisplay (_base));
1623 // Check for double-click
1625 if ((event->xbutton.time - lastTime) <= multiClick)
1629 lastTime = event->xbutton.time;
1639 XsMoveOutline move (_base);
1643 if (move.go ( ) != False)
1646 // Relocate the icon
1648 _win->setPosition (move.x ( ), move.y ( ));
1657 void _XsMotifIcon::_expose (XEvent *)
1659 if (_topShadowGC == 0) // JACS
1662 Dimension iconHeight;
1663 Dimension iconWidth;
1665 // Compute icon size
1667 XtVaGetValues (_base, XmNwidth, &iconWidth, XmNheight, &iconHeight, NULL);
1671 _drawShadows (0, 0, iconWidth, iconHeight, 2);
1673 // Figure out the icon string
1675 const char *iconName = (_iconName != 0) ? _iconName : (_win->title ( ) != 0) ?
1676 _win->title ( ) : _win->name ( );
1678 const int fontX = 3;
1679 const int fontY = 3;
1681 if ((iconName != 0) && (iconName[0] != '\0'))
1684 int len = strlen (iconName);
1686 // Compute the text size
1688 textWidth = XTextWidth (_iconFont, iconName, len);
1690 // Center the text in the bottom of the icon (or left-justify it)
1694 if (textWidth <= (iconWidth - (fontX * 2)))
1695 x = (iconWidth - (int)textWidth) / 2;
1699 y = (int)iconHeight - _iconFont->descent - fontY;
1703 XDrawString (XtDisplay (_base), XtWindow (_base), _fontGC,
1704 x, y, iconName, len);
1707 // Compute label size
1709 int labelHeight = _iconFont->descent + _iconFont->ascent + (fontY * 2);
1711 if (labelHeight >= (iconHeight - 6))
1714 // Draw the separator
1716 int sepY = (iconHeight) - labelHeight;
1718 _drawLine (1, sepY, iconWidth - 2, sepY, _bottomShadowGC);
1719 _drawLine (1, sepY + 1, iconWidth - 2, sepY + 1, _topShadowGC);
1721 // Draw the pixmap frame
1723 const int frameX = 4;
1724 const int frameY = 4;
1726 if ((frameX + 6) >= sepY)
1729 int frameWidth = iconWidth - (frameX * 2);
1730 int frameHeight = sepY - frameY - 2;
1732 _drawShadows (frameX, frameY, frameWidth, frameHeight, 1, True);
1737 _drawShadows (frameX + 1, frameY + 1, frameWidth, frameHeight, 1);
1746 if ((frameWidth > 0) && (frameHeight > 0))
1751 // Center the pixmap or top-left orient it
1753 if (frameWidth > _width)
1755 origX = (frameWidth - _width) / 2;
1756 origX += frameX + 2;
1765 if (frameHeight > _height)
1767 origY = (frameHeight - _height) / 2;
1768 origY += frameY + 2;
1774 drawH = frameHeight;
1777 XCopyArea (XtDisplay (_base), _pixmap, XtWindow (_base), _pixmapGC,
1778 0, 0, drawW, drawH, origX, origY);
1785 void _XsMotifIcon::_map ( )
1787 unsigned long valuemask;
1793 // Call the base-class
1795 _XsMotifComponent::_map ( );
1797 // Get the icon pixels
1799 XtVaGetValues (_win->base ( ), XmNdepth, &depth, XmNbackground, &bg,
1800 XmNforeground, &fg, NULL);
1802 // Create the default icon pixmap
1806 _pixmap = XCreatePixmapFromBitmapData (XtDisplay (_base), XtWindow (_base),
1807 xs_motif_icon_bits, xs_motif_icon_width, xs_motif_icon_height,
1812 setPixmap (_pixmap);
1816 // Create the icon pixmap graphics context
1818 valuemask = GCGraphicsExposures | GCForeground | GCBackground;
1820 values.graphics_exposures = False;
1821 values.foreground = fg;
1822 values.background = bg;
1824 _pixmapGC = XtGetGC (_base, valuemask, &values);
1827 // Create the font graphics context
1829 valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
1831 values.foreground = fg;
1832 values.background = bg;
1833 values.font = _iconFont->fid;
1834 values.graphics_exposures = False;
1836 _fontGC = XtGetGC (_base, valuemask, &values);
1840 ----------------------------------------------------------------------------
1844 // Static definitions
1846 int _XsMotifMenu::_count = 0;
1847 Cursor _XsMotifMenu::_cursor = None;
1848 Pixmap _XsMotifMenu::_stipple = None;
1849 Display *_XsMotifMenu::_dpy = 0;
1853 XtResource _XsMotifMenu::_resourceList[] = {
1859 XtOffset (_XsMotifMenu*, _saveUnder),
1868 XtOffset (_XsMotifMenu*, _strings[Restore]),
1877 XtOffset (_XsMotifMenu*, _strings[Move]),
1886 XtOffset (_XsMotifMenu*, _strings[Size]),
1895 XtOffset (_XsMotifMenu*, _strings[Minimize]),
1904 XtOffset (_XsMotifMenu*, _strings[Maximize]),
1913 XtOffset (_XsMotifMenu*, _strings[Raise]),
1922 XtOffset (_XsMotifMenu*, _strings[Lower]),
1931 XtOffset (_XsMotifMenu*, _strings[Close]),
1939 sizeof (XFontStruct*),
1940 XtOffset (_XsMotifMenu*, _menuFont),
1942 "-*-helvetica-bold-o-normal-*-14-*-*-*-*-*-iso8859-1"
1948 _XsMotifMenu::_XsMotifMenu (const char *name, XsMotifWindow *win) :
1949 _XsMotifBase (name, win)
1952 // Create the cursor (if necessary)
1957 // Create the menu cursor
1959 _cursor = XCreateFontCursor (XtDisplay (win->base ( )), XC_arrow);
1961 // Create a stippled pixmap
1963 Widget parent = _win->base ( );
1968 XtVaGetValues (parent, XmNforeground, &foreground, XmNbackground,
1969 &background, XmNdepth, &depth, NULL);
1971 const int pixmapWidth = 2;
1972 const int pixmapHeight = 2;
1973 static unsigned char pixmapBits[] = { 0x02, 0x01 };
1975 _dpy = XtDisplay (parent);
1976 _stipple = XCreatePixmapFromBitmapData (_dpy, DefaultRootWindow (_dpy),
1977 (char*)pixmapBits, pixmapWidth, pixmapHeight, foreground, background,
1987 // Create the component (why doesn't overrideShell work?)
1989 _base = XtVaCreatePopupShell (_name, topLevelShellWidgetClass,
1990 XtParent (_win->base ( )), XmNoverrideRedirect, True,
1991 XmNborderWidth, 1, NULL);
1993 // Install destroy handler
1995 _installDestroyHandler ( );
1997 // Install event handler ('cause we never call _XsMotifBase::show)
1999 XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
2003 _getResources (_resourceList, XtNumber (_resourceList));
2005 // Get the background color
2009 XtVaGetValues (_win->base ( ), XmNbackground, &bg, NULL);
2011 // Compute the size of the (largest) menu item
2013 int textHeight = _menuFont->ascent + _menuFont->descent;
2017 for (int loop = 0; loop < Num; loop++)
2019 tmp = XTextWidth (_menuFont, _strings[loop], strlen (_strings[loop]));
2021 if (tmp > textWidth)
2025 // Put a border around the buttons
2027 textWidth += (2 * HorizTextOffset);
2028 textHeight += (2 * VertTextOffset);
2031 The menu height is the menu-shadow (1 pixel on top and bottom) + the
2035 int menuHeight = (2 * ShadowThickness) + // Top and bottom shadow
2036 (textHeight * Num); // The menu items
2039 The menu width is the menu-shadow (1 pixel on the left and right) +
2040 the largest menu text (calculated above)
2043 int menuWidth = (2 * ShadowThickness) + // Left and right shadow
2044 textWidth; // Largest text item
2046 // Configure the popup
2048 XtVaSetValues (_base, XmNsaveUnder, _saveUnder, XmNwidth, menuWidth,
2049 XmNheight, menuHeight, NULL);
2054 _XsMotifMenu::~_XsMotifMenu ( )
2057 XtReleaseGC (_base, _fontGC);
2060 XtReleaseGC (_base, _grayGC);
2063 XtReleaseGC (_base, _backgroundGC);
2065 // Free the pixmap (if necessary)
2068 XFreePixmap (_dpy, _stipple);
2073 void _XsMotifMenu::popup (Boolean atPointer)
2075 assert (_base != 0);
2079 // Compute the location of the menu.
2088 // Menu at pointer location
2090 XQueryPointer (XtDisplay (_base), XtWindow (XtParent (_base)),
2091 &win, &win, &rootX, &rootY, &winX, &winY, &mask);
2093 x = (Position)rootX;
2094 y = (Position)rootY;
2099 // Menu at top-left corner of client area
2101 XtTranslateCoords (_win->clientArea ( ), 0, 0, &x, &y);
2106 XtVaSetValues (_base, XmNx, x, XmNy, y, NULL);
2108 // Initialize the item
2114 XtPopup (_base, XtGrabNone);
2118 if (_grabPointer ( ) == FALSE)
2125 // Pop the menu down
2129 // Ungrab the pointer
2133 if (_curItem != NoItem)
2137 Post a work-proc to process this item. This will allow everything
2138 to get caught up before we process the menu item
2141 XtAppContext appContext = XtWidgetToApplicationContext (_base);
2142 XtAppAddWorkProc (appContext, _workProc, (XtPointer)this);
2148 const char *_XsMotifMenu::className ( ) const
2150 return ("_XsMotifMenu");
2153 // _componentDestroyed
2155 void _XsMotifMenu::_componentDestroyed ( )
2161 XtReleaseGC (_base, _fontGC);
2164 XtReleaseGC (_base, _grayGC);
2167 XtReleaseGC (_base, _backgroundGC);
2173 // Call the base-class
2175 _XsMotifBase::_componentDestroyed ( );
2180 void _XsMotifMenu::_processEvents ( )
2182 assert (_base != 0);
2184 XtAppContext appContext = XtWidgetToApplicationContext (_base);
2186 Display *dpy = XtDisplay (_base);
2191 XtAppNextEvent (appContext, &event);
2193 // Process this event
2211 // Process only the last motion event
2213 while (XPending (dpy) > 0)
2215 XPeekEvent (dpy, &next);
2216 if (next.type != MotionNotify)
2218 XtAppNextEvent (appContext, &event);
2221 // Track the mouse and toggle the menu items
2223 Item item = _trackPointer ((XMotionEvent*)&event);
2225 // Unselect the current item (if the item is different)
2227 if (item != _curItem)
2229 _toggleItem (_curItem, False);
2231 // Select the new item
2233 _toggleItem ((_curItem = item), True);
2240 XtDispatchEvent (&event);
2249 void _XsMotifMenu::_processItem (Item item)
2263 Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
2265 // Warp the pointer to the center of the window
2267 Dimension width, height;
2268 XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
2270 XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
2271 (width / 2), (height / 2));
2275 XsMoveOutline move (base);
2279 if (move.go (True) != False)
2282 // Relocate the window
2284 _win->setPosition (move.x ( ), move.y ( ));
2290 Widget base = (_win->minimized ( )) ? _win->icon ( ) : _win->base ( );
2292 // Warp the pointer to the center of the window
2294 Dimension width, height;
2295 XtVaGetValues (base, XmNwidth, &width, XmNheight, &height, NULL);
2297 XWarpPointer (XtDisplay (_base), None, XtWindow (base), 0, 0, 0, 0,
2298 (width / 2), (height / 2));
2300 // Resize the window
2302 XsResizeOutline resize (_win->base ( ), XsResizeOutline::Undetermined);
2303 resize.setMinSize (_win->minWidth ( ), _win->minHeight ( ));
2307 if (resize.go (True) != False)
2310 // Relocate the window
2312 _win->setPosition (resize.x ( ), resize.y ( ));
2313 _win->setSize (resize.width ( ), resize.height ( ));
2349 void _XsMotifMenu::_redrawMenu ( )
2353 // Get the size of the menu
2355 XtVaGetValues (_base, XmNwidth, &w, XmNheight, &h, NULL);
2357 // Draw a shadow around the menu
2359 _drawShadows (0, 0, w, h, ShadowThickness);
2361 // Cycle and draw all of the elements
2363 for (int loop = 0; loop < Num; loop++)
2364 _redrawItem ((Item)loop);
2369 void _XsMotifMenu::_redrawItem (Item item)
2374 int x = ShadowThickness + HorizTextOffset;
2378 Compute the y-position of the element. This will be the size of the
2379 top-shadow + the items before it + the offset of the item itself
2382 y = ShadowThickness + // Top shadow
2383 (item * ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent))) +
2384 (VertTextOffset + _menuFont->ascent); // The item iteself
2386 // Figure out the graphics-context
2390 if (_win->minimized ( ))
2391 gc = ((item == Size) || (item == Minimize)) ? _grayGC : _fontGC;
2392 else if (_win->maximized ( ))
2393 gc = (item == Maximize) ? _grayGC : _fontGC;
2395 gc = (item == Restore) ? _grayGC : _fontGC;
2399 XDrawString (XtDisplay (_base), XtWindow (_base), gc, x, y,
2400 _strings[item], strlen (_strings[item]));
2405 void _XsMotifMenu::_toggleItem (Item item, Boolean active)
2411 Either draw the background of the specified item in the active color
2412 or the standard background color
2415 GC gc = (active) ? _topShadowGC : _backgroundGC;
2417 // Get the width of the menu
2419 Dimension menuWidth;
2420 XtVaGetValues (_base, XmNwidth, &menuWidth, NULL);
2422 // Compute the location and size of the rectangle
2425 unsigned int width, height;
2427 x = ShadowThickness;
2428 height = ((VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent));
2429 y = ShadowThickness + (item * height);
2430 width = menuWidth - (2 * ShadowThickness);
2432 // Draw the filled rectangle
2434 XFillRectangle (XtDisplay (_base), XtWindow (_base), gc, x, y, width, height);
2443 _XsMotifMenu::Item _XsMotifMenu::_trackPointer (XMotionEvent *event)
2445 assert (_base != 0);
2447 Dimension menuWidth;
2448 Dimension menuHeight;
2451 // Get the menu size and position
2453 XtVaGetValues (_base, XmNwidth, &menuWidth, XmNheight, &menuHeight,
2454 XmNx, &x, XmNy, &y, NULL);
2456 // Make sure the pointer is in the menu
2458 if ((event->x_root < x) || (event->x_root > (x + menuWidth)))
2461 if ((event->y_root < y) || (event->y_root > (y + menuHeight)))
2464 // Make sure the pointer is on the confines of the shadow
2466 if ((event->x < ShadowThickness) || (event->x > (menuWidth - (2 * ShadowThickness))))
2469 if ((event->y < ShadowThickness) || (event->y > (menuHeight - (2 * ShadowThickness))))
2473 Now we are just concerned with the y-position. Subtract off the
2474 shadow thickness to normalize the location
2477 int yPos = event->y - ShadowThickness;
2479 // Compute which item the mouse is in
2481 int itemHeight = (VertTextOffset * 2) + (_menuFont->descent + _menuFont->ascent);
2483 Item item = (Item)(yPos / itemHeight);
2485 // Validate that the item is not grayed-out
2487 if (_win->minimized ( ))
2489 if ((item == Size) || (item == Minimize))
2492 else if (_win->maximized ( ))
2494 if (item == Maximize)
2497 else if (item == Restore)
2505 Boolean _XsMotifMenu::_grabPointer ( )
2508 // Sync everything up before being grabby
2510 XSync (XtDisplay (_base), False);
2514 if (XGrabPointer (XtDisplay (_base), XtWindow (_base), False,
2515 (unsigned int)(ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
2516 EnterWindowMask | LeaveWindowMask), GrabModeAsync,
2517 GrabModeAsync, None, _cursor, CurrentTime) != GrabSuccess)
2519 XBell (XtDisplay (_base), 100);
2528 void _XsMotifMenu::_ungrabPointer ( )
2531 // Ungrab the pointer
2533 XUngrabPointer (XtDisplay (_base), CurrentTime);
2535 // Sync everything back up
2537 XSync (XtDisplay (_base), False);
2542 void _XsMotifMenu::_map ( )
2545 // Call the base-class
2547 _XsMotifBase::_map ( );
2549 unsigned long valuemask;
2556 XtVaGetValues (XtParent (_base), XmNforeground, &foreground, NULL);
2557 XtVaGetValues (_base, XmNbackground, &background, NULL);
2559 // Create the font graphics context
2561 valuemask = GCForeground | GCBackground | GCGraphicsExposures | GCFont;
2563 values.foreground = foreground;
2564 values.background = background;
2565 values.font = _menuFont->fid;
2566 values.graphics_exposures = False;
2568 _fontGC = XtGetGC (_base, valuemask, &values);
2570 // Create the insensitive font graphics context
2572 valuemask |= (GCFillStyle | GCTile);
2574 values.fill_style = FillTiled;
2575 values.tile = _stipple;
2577 _grayGC = XtGetGC (_base, valuemask, &values);
2579 // Create the background contexts
2581 valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
2582 values.line_width = 0;
2583 values.graphics_exposures = False;
2584 values.foreground = background;
2586 _backgroundGC = XtGetGC (_base, valuemask, &values);
2591 Boolean _XsMotifMenu::_workProc (XtPointer clientData)
2593 _XsMotifMenu *obj = (_XsMotifMenu*)clientData;
2594 if (obj->_curItem != NoItem)
2595 obj->_processItem (obj->_curItem);
2601 ----------------------------------------------------------------------------
2605 // Static definitions
2607 XtResource XsMotifWindow::_resourceList[] = {
2613 XtOffset (XsMotifWindow*, _showBorder),
2622 XtOffset (XsMotifWindow*, _showResize),
2631 XtOffset (XsMotifWindow*, _showTitle),
2640 XtOffset (XsMotifWindow*, _showMenu),
2649 XtOffset (XsMotifWindow*, _showMinimize),
2658 XtOffset (XsMotifWindow*, _showMaximize),
2667 XtOffset (XsMotifWindow*, _lowerOnIconify),
2676 XtOffset (XsMotifWindow*, _minW),
2678 (XtPointer)((BorderSize_ + ButtonSize_) * 3)
2685 XtOffset (XsMotifWindow*, _maxW),
2694 XtOffset (XsMotifWindow*, _minH),
2696 (XtPointer)((BorderSize_ + ButtonSize_) * 3)
2703 XtOffset (XsMotifWindow*, _maxH),
2711 XsMotifWindow::XsMotifWindow (const char *name) : XsMDIWindow (name)
2717 for (loop = 0; loop < _XsMotifSide::Max; loop++)
2723 for (loop = 0; loop < _XsMotifButton::Max; loop++)
2736 XsMotifWindow::~XsMotifWindow ( )
2740 for (loop = 0; loop < _XsMotifSide::Max; loop++)
2742 delete _corners[loop];
2743 delete _sides[loop];
2746 for (loop = 0; loop < _XsMotifButton::Max; loop++)
2747 delete _buttons[loop];
2756 void XsMotifWindow::raise ( )
2758 Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2760 XRaiseWindow (XtDisplay (w), XtWindow (w));
2765 void XsMotifWindow::lower ( )
2767 Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2769 XLowerWindow (XtDisplay (w), XtWindow (w));
2774 void XsMotifWindow::minimize ( )
2776 assert (_base != 0);
2778 // Check if we are already minimized
2780 if (_minimized == True)
2783 // Minimize the window
2789 // Lower (if necessary)
2791 if (_lowerOnIconify)
2799 void XsMotifWindow::maximize ( )
2801 assert (_base != 0);
2803 // Check if we are already in this state
2805 if (_maximized == True)
2808 // Restore (if necessary)
2813 // Save current dimensions
2815 XtVaGetValues (_base, XmNx, &_savedX, XmNy, &_savedY, XmNwidth,
2816 &_savedWidth, XmNheight, &_savedHeight, NULL);
2819 Constrain the new window size. The size of the maximized window
2820 is equal to the size of the current clip-window of the canvas.
2823 const Dimension offset = 5; // Border around max'd window
2825 Widget clipWindow = XtParent (XtParent (_base));
2826 assert (clipWindow != 0);
2827 Dimension clipW, clipH;
2831 XtVaGetValues (clipWindow, XmNheight, &clipH, XmNwidth, &clipW, NULL);
2835 if (clipW > (offset * 2))
2836 clipW -= (offset * 2);
2838 if (clipH > (offset * 2))
2839 clipH -= (offset * 2);
2841 // Compute the new window position (map clip-window to work-area)
2843 XTranslateCoordinates (XtDisplay (_base), XtWindow (clipWindow),
2844 XtWindow (XtParent (_base)), (int)offset, (int)offset,
2845 &newX, &newY, &child);
2847 // Set new maximum dimensions
2849 setPosition ((Position)newX, (Position)newY);
2850 setSize (clipW, clipH);
2854 // Redraw the maximize button
2856 _buttons[_XsMotifButton::Maximize]->redraw ( );
2861 void XsMotifWindow::restore ( )
2863 assert (_base != 0);
2865 // Check if we are already restored
2867 if ((_maximized == False) && (_minimized == False))
2870 // Either un-minimize or un-maximize
2875 // Restore the window
2880 // If maximized, restore again
2892 // Restore saved dimensions
2894 setPosition (_savedX, _savedY);
2895 setSize (_savedWidth, _savedHeight);
2901 void XsMotifWindow::close ( )
2905 Don't delete the window (because its not ours to delete).
2917 void XsMotifWindow::setTitle (const char *title)
2920 _title->setTitle (title);
2925 void XsMotifWindow::setIconName (const char *iconName)
2928 _icon->setIconName (iconName);
2933 void XsMotifWindow::setPixmap (Pixmap pixmap)
2936 _icon->setPixmap (pixmap);
2941 void XsMotifWindow::popupMenu (Boolean b)
2949 void XsMotifWindow::setPosition (Position x, Position y)
2953 Widget w = (_minimized == True) ? _icon->base ( ) : _base;
2955 XtVaSetValues (w, XmNx, x, XmNy, y, NULL);
2958 XsMDIWindow::setPosition (x, y); // Cache the points
2963 void XsMotifWindow::setSize (Dimension w, Dimension h)
2966 // Set the window size
2972 else if ((_maxW != (Dimension)-1) && (w > _maxW))
2977 else if ((_maxH != (Dimension)-1) && (h > _maxH))
2980 if (_minimized == False)
2981 XtVaSetValues (_base, XmNwidth, w, XmNheight, h, NULL);
2983 // If window was maximized, change the window state back to normal
2985 if (_maximized == True)
2989 // Redraw the maximize button
2991 _buttons[_XsMotifButton::Maximize]->redraw ( );
2995 XsMDIWindow::setSize (w, h); // Cache the points
3000 const char* XsMotifWindow::className ( ) const
3002 return ("XsMotifWindow");
3007 void XsMotifWindow::_createWindow (Widget parent)
3009 assert (parent != 0);
3011 // Create the window frame
3013 _base = XtVaCreateWidget (_name, xmFormWidgetClass, parent,
3014 XmNborderWidth, (Dimension)1, NULL);
3016 // Install destroy handler
3018 _installDestroyHandler ( );
3022 _getResources (_resourceList, XtNumber (_resourceList));
3025 Fix configuration inter-dependencies. Here are the rules:
3027 1) If there is no border, then there are no resize handles
3028 2) If there is no title, then there are no buttons (would look stupid)
3031 if (_showBorder == False)
3032 _showResize = False;
3034 if (_showTitle == False)
3037 _showMinimize = False;
3038 _showMaximize = False;
3050 _corners[_XsMotifCorner::TopLeft] = new _XsMotifCorner ("topLeft", this, _XsMotifCorner::TopLeft);
3052 XtVaSetValues (_corners[_XsMotifCorner::TopLeft]->base ( ), XmNtopAttachment,
3053 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
3054 XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3058 _corners[_XsMotifCorner::TopRight] = new _XsMotifCorner ("topRight", this, _XsMotifCorner::TopRight);
3060 XtVaSetValues (_corners[_XsMotifCorner::TopRight]->base ( ), XmNtopAttachment,
3061 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment,
3062 XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3066 _corners[_XsMotifCorner::BottomLeft] = new _XsMotifCorner ("bottomLeft", this, _XsMotifCorner::BottomLeft);
3068 XtVaSetValues (_corners[_XsMotifCorner::BottomLeft]->base ( ), XmNtopAttachment,
3069 XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
3070 XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3074 _corners[_XsMotifCorner::BottomRight] = new _XsMotifCorner ("bottomRight", this, _XsMotifCorner::BottomRight);
3076 XtVaSetValues (_corners[_XsMotifCorner::BottomRight]->base ( ), XmNtopAttachment,
3077 XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,
3078 XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3090 _sides[_XsMotifSide::Top] = new _XsMotifSide ("top", this, _XsMotifSide::Top);
3092 XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNtopAttachment,
3093 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_NONE, NULL);
3097 XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNleftAttachment,
3098 XmATTACH_WIDGET, XmNleftWidget, _corners[_XsMotifCorner::TopLeft]->base ( ),
3099 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3100 _corners[_XsMotifCorner::TopRight]->base ( ), NULL);
3104 XtVaSetValues (_sides[_XsMotifSide::Top]->base ( ), XmNleftAttachment,
3105 XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3110 _sides[_XsMotifSide::Bottom] = new _XsMotifSide ("bottom", this, _XsMotifSide::Bottom);
3112 XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNtopAttachment,
3113 XmATTACH_NONE, XmNbottomAttachment, XmATTACH_FORM, NULL);
3117 XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNleftAttachment,
3118 XmATTACH_WIDGET, XmNleftWidget, _corners[_XsMotifCorner::BottomLeft]->base ( ),
3119 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3120 _corners[_XsMotifCorner::BottomRight]->base ( ), NULL);
3124 XtVaSetValues (_sides[_XsMotifSide::Bottom]->base ( ), XmNleftAttachment,
3125 XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3130 _sides[_XsMotifSide::Left] = new _XsMotifSide ("left", this, _XsMotifSide::Left);
3132 XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNleftAttachment,
3133 XmATTACH_FORM, XmNrightAttachment, XmATTACH_NONE, NULL);
3137 XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNtopAttachment,
3138 XmATTACH_WIDGET, XmNtopWidget, _corners[_XsMotifCorner::TopLeft]->base ( ),
3139 XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
3140 _corners[_XsMotifCorner::BottomLeft]->base ( ), NULL);
3144 XtVaSetValues (_sides[_XsMotifSide::Left]->base ( ), XmNtopAttachment,
3145 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
3150 _sides[_XsMotifSide::Right] = new _XsMotifSide ("right", this, _XsMotifSide::Right);
3152 XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNleftAttachment,
3153 XmATTACH_NONE, XmNrightAttachment, XmATTACH_FORM, NULL);
3157 XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNtopAttachment,
3158 XmATTACH_WIDGET, XmNtopWidget, _corners[_XsMotifCorner::TopRight]->base ( ),
3159 XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
3160 _corners[_XsMotifCorner::BottomRight]->base ( ), NULL);
3164 XtVaSetValues (_sides[_XsMotifSide::Right]->base ( ), XmNtopAttachment,
3165 XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL);
3173 _buttons[_XsMotifButton::Menu] = new _XsMotifButton ("menu", this, _XsMotifButton::Menu);
3175 XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNbottomAttachment,
3176 XmATTACH_NONE, XmNrightAttachment, XmATTACH_NONE, NULL);
3180 XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
3181 XmATTACH_WIDGET, XmNleftWidget, _sides[_XsMotifSide::Left]->base ( ),
3182 XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3187 XtVaSetValues (_buttons[_XsMotifButton::Menu]->base ( ), XmNleftAttachment,
3188 XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, NULL);
3196 _buttons[_XsMotifButton::Maximize] = new _XsMotifButton ("maximize", this, _XsMotifButton::Maximize);
3198 XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNbottomAttachment,
3199 XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE, NULL);
3203 XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
3204 XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3205 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
3210 XtVaSetValues (_buttons[_XsMotifButton::Maximize]->base ( ), XmNtopAttachment,
3211 XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL);
3219 _buttons[_XsMotifButton::Minimize] = new _XsMotifButton ("minimize", this, _XsMotifButton::Minimize);
3221 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3222 XmNbottomAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_NONE,
3227 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ), XmNtopAttachment,
3228 XmATTACH_WIDGET, XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3229 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3230 _sides[_XsMotifSide::Right]->base ( ), NULL);
3234 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3235 XmNtopAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
3241 XtVaSetValues (_buttons[_XsMotifButton::Minimize]->base ( ),
3242 XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget,
3243 _buttons[_XsMotifButton::Maximize]->base ( ), NULL);
3253 _title = new _XsMotifTitle ("title", this);
3255 XtVaSetValues (_title->base ( ), XmNbottomAttachment, XmATTACH_NONE,
3260 XtVaSetValues (_title->base ( ), XmNtopAttachment, XmATTACH_WIDGET,
3261 XmNtopWidget, _sides[_XsMotifSide::Top]->base ( ),
3262 XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget,
3263 _sides[_XsMotifSide::Left]->base ( ), XmNrightAttachment,
3264 XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
3269 XtVaSetValues (_title->base ( ), XmNtopAttachment, XmATTACH_FORM,
3270 XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM,
3276 XtVaSetValues (_title->base ( ), XmNleftAttachment, XmATTACH_WIDGET,
3277 XmNleftWidget, _buttons[_XsMotifButton::Menu]->base ( ), NULL);
3280 Widget ba = (_buttons[_XsMotifButton::Minimize] != 0) ?
3281 _buttons[_XsMotifButton::Minimize]->base ( ) :
3282 (_buttons[_XsMotifButton::Maximize] != 0) ?
3283 _buttons[_XsMotifButton::Maximize]->base ( ) : 0;
3287 XtVaSetValues (_title->base ( ), XmNrightAttachment, XmATTACH_WIDGET,
3288 XmNrightWidget, ba, NULL);
3296 _icon = new _XsMotifIcon ("icon", this, parent);
3302 _menu = new _XsMotifMenu ("menu", this);
3308 _clientArea = XtVaCreateWidget ("clientArea", xmFormWidgetClass, _base, NULL);
3312 XtVaSetValues (_clientArea, XmNleftAttachment, XmATTACH_WIDGET,
3313 XmNleftWidget, _sides[_XsMotifSide::Left]->base ( ), XmNrightAttachment,
3314 XmATTACH_WIDGET, XmNrightWidget, _sides[_XsMotifSide::Right]->base ( ),
3315 XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget,
3316 _sides[_XsMotifSide::Bottom]->base ( ), NULL);
3320 XtVaSetValues (_clientArea, XmNleftAttachment, XmATTACH_FORM,
3321 XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM,
3325 Widget topW = (_showTitle) ? _title->base ( ) :
3326 (_showBorder) ? _sides[_XsMotifSide::Top]->base ( ) : 0;
3330 XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_WIDGET,
3331 XmNtopWidget, topW, NULL);
3334 XtVaSetValues (_clientArea, XmNtopAttachment, XmATTACH_FORM, NULL);
3336 // Call the class function to create the contents of the window
3338 _buildClientArea (_clientArea);
3340 // Add an event handler to be called when this window is mapped
3342 XtAddEventHandler (_base, StructureNotifyMask, False, _mapEventHandler, (XtPointer)this);
3348 for (loop = 0; loop < _XsMotifSide::Max; loop++)
3350 if (_corners[loop] != 0)
3351 _corners[loop]->show ( );
3352 if (_sides[loop] != 0)
3353 _sides[loop]->show ( );
3356 for (loop = 0; loop < _XsMotifButton::Max; loop++)
3358 if (_buttons[loop] != 0)
3359 _buttons[loop]->show ( );
3368 void XsMotifWindow::_mapEvent ( )
3371 // Raise the client-area
3373 XRaiseWindow (XtDisplay (_clientArea), XtWindow (_clientArea));
3378 void XsMotifWindow::_mapEventHandler (Widget, XtPointer clientData, XEvent *event, Boolean*)
3380 if (event->type == MapNotify)
3382 XsMotifWindow *obj = (XsMotifWindow*)clientData;
3384 XtRemoveEventHandler (obj->_base, StructureNotifyMask, False, obj->_mapEventHandler, clientData);