1 /*
2    Copyright (C) 1996 Scott W. Sadler
3    All rights reserved.
4 */
5 
6 /*
7    XsMDICanvas.C
8 
9    History
10       03-Mar-96 1.0; Scott W. Sadler (ssadler@cisco.com)
11                      Created
12 */
13 
14 // Includes
15 
16 #include <assert.h>
17 #include <Xm/ScrolledW.h>
18 #include <Xm/DrawingA.h>
19 #include "XsMDICanvas.h"
20 #include "XsMDIWindow.h"
21 
22 // Static definitions
23 
24 String XsMDICanvas::_resources[] = {
25    "*canvas.resizePolicy:     XmRESIZE_GROW",
26    NULL
27 };
28 
29 // Constructor
30 
XsMDICanvas(const char * name,Widget parent)31 XsMDICanvas::XsMDICanvas (const char *name, Widget parent) : XsComponent (name)
32 {
33    assert (parent != 0);
34 
35 // Initialize
36 
37    _list = 0;
38    _num = 0;
39    _max = 0;
40    _place = 0;
41 
42 // Install resources
43 
44    _setResources (parent, _resources);
45 
46 // Create the scrolled window
47 
48    const int nargs = 10;
49    Arg   args[nargs];
50    int   n = 0;
51 
52    XtSetArg (args[n], XmNscrollingPolicy, XmAUTOMATIC);   n++;
53    XtSetArg (args[n], XmNscrolledWindowMarginHeight, (Dimension)0);  n++;
54    XtSetArg (args[n], XmNscrolledWindowMarginWidth, (Dimension)0);   n++;
55    XtSetArg (args[n], XmNmarginHeight, (Dimension)5);    n++;
56    XtSetArg (args[n], XmNmarginWidth, (Dimension)5);     n++;
57 
58    assert (n <= nargs);
59 
60    _base = XmCreateScrolledWindow (parent, _name, args, n);
61 
62 // Install the destroy handler
63 
64    _installDestroyHandler ( );
65 
66 // Create the drawing area (canvas)
67 
68    _drawArea = XtVaCreateWidget ("canvas", xmDrawingAreaWidgetClass,
69       _base, XmNmarginHeight, (Dimension)0, XmNmarginWidth, (Dimension)0,
70       NULL);
71 
72 // Set resize callback on drawing area
73 
74    XtAddCallback (_drawArea, XmNresizeCallback, _canvasResizeCallback, (XtPointer)this);
75 
76 // Set resize callback on clip window
77 
78    XtVaGetValues (_base, XmNclipWindow, &_clipWin, NULL);
79    XtAddCallback (_clipWin, XmNresizeCallback, _clipResizeCallback, (XtPointer)this);
80 }
81 
82 // Destructor
83 
~XsMDICanvas()84 XsMDICanvas::~XsMDICanvas ( )
85 {
86 
87 /*
88    Remove callbacks to prevent calls to destroyed class-part of XsMDICanvas
89    while children are being destroyed.
90 */
91 
92    if (_drawArea)
93       XtRemoveCallback (_drawArea, XmNresizeCallback, _canvasResizeCallback, (XtPointer)this);
94 
95    if (_clipWin)
96       XtRemoveCallback (_clipWin, XmNresizeCallback, _clipResizeCallback, (XtPointer)this);
97 
98 // Remove all windows
99 
100    removeAll ( );
101 }
102 
103 // add
104 
add(XsMDIWindow * win)105 void XsMDICanvas::add (XsMDIWindow *win)
106 {
107    assert (win != 0);
108 
109    const int increment = 10;
110 
111 // Check if we need to allocate more space
112 
113    if (_num >= _max)
114    {
115       XsMDIWindow **newList = new XsMDIWindow*[_max + increment];
116 
117       for (int loop = 0; loop < _num; loop++)
118          newList[loop] = _list[loop];
119       _max += increment;
120 
121       delete [] _list;
122       _list = newList;
123    }
124 
125 // Add the new window
126 
127    _list[_num++] = win;
128 
129 // Install the parent canvas
130 
131    win->_setWindowParent (_drawArea);
132 
133 // If the canvas is shown, place the window
134 
135    if (XtIsManaged (_base))
136       _placeWindow (win);
137 }
138 
139 // remove
140 
remove(XsMDIWindow * win)141 void XsMDICanvas::remove (XsMDIWindow *win)
142 {
143    assert (win != 0);
144 
145 // Remove the window
146 
147    int   i, j;
148 
149    for (i = 0; i < _num; i++)
150    {
151       if (_list[i] == win)
152       {
153          win->hide ( );
154          win->_setWindowParent (0);
155 
156          for (j = i; j < _num - 1; j++)
157             _list[j] = _list[j + 1];
158          _num--;
159 
160          return;
161       }
162    }
163 
164    assert (0);    // Couldn't find window
165 }
166 
167 // removeAll
168 
removeAll()169 void XsMDICanvas::removeAll ( )
170 {
171 
172 // Delete and reset the list
173 
174    delete [] _list;
175 
176    _list = 0;
177    _num = 0;
178    _max = 0;
179 }
180 
181 // show
182 
show()183 void XsMDICanvas::show ( )
184 {
185    assert (_drawArea != 0);
186 
187 // Place all of the child windows
188 
189    for (int loop = 0; loop < _num; loop++)
190       _placeWindow (_list[loop]);
191 
192 // Manage the drawing area and canvas
193 
194    XtManageChild (_drawArea);
195 
196 // Call base class
197 
198    XsComponent::show ( );
199 }
200 
201 // className
202 
className()203 const char* XsMDICanvas::className ( ) const
204 {
205    return ("XsMDICanvas");
206 }
207 
208 // _componentDestroyed
209 
_componentDestroyed()210 void XsMDICanvas::_componentDestroyed ( )
211 {
212 
213 // Remove the callbacks
214 
215    XtRemoveCallback (_drawArea, XmNresizeCallback, _canvasResizeCallback, (XtPointer)this);
216    XtRemoveCallback (_clipWin, XmNresizeCallback, _clipResizeCallback, (XtPointer)this);
217 
218    _drawArea = 0;
219    _clipWin = 0;
220 }
221 
222 // _placeWindow
223 
_placeWindow(XsMDIWindow * win)224 void XsMDICanvas::_placeWindow (XsMDIWindow *win)
225 {
226    assert (win != 0);
227 
228 // Compute window placement
229 
230    Position x, y;
231 
232    const int maxWin = 10;
233    const Position offset = 20;
234    const Position minOffset = 10;
235 
236    x = (_place * offset) + minOffset;
237    y = (_place * offset) + minOffset;
238 
239    if (++_place == maxWin)
240       _place = 0;
241 
242 // Set the window placement
243 
244    win->setPosition (x, y);
245 
246 // Show the window
247 
248    win->show ( );
249 }
250 
251 // _resize
252 
_resize(XtPointer)253 void XsMDICanvas::_resize (XtPointer)
254 {
255    Dimension   clipHeight;
256    Dimension   clipWidth;
257    Dimension   canvasHeight;
258    Dimension   canvasWidth;
259 
260 // Check if clip window and canvas are managed
261 
262    if (!XtIsManaged (_clipWin) || !XtIsManaged (_drawArea))
263       return;
264 
265 // Get the clip window size
266 
267    XtVaGetValues (_clipWin, XmNwidth, &clipWidth, XmNheight, &clipHeight, NULL);
268 
269 // Get the canvas size
270 
271    XtVaGetValues (_drawArea, XmNwidth, &canvasWidth, XmNheight, &canvasHeight, NULL);
272 
273 // Force the canvas to be at least as big as the clip window
274 
275    if (canvasWidth < clipWidth)
276       canvasWidth = clipWidth;
277    if (canvasHeight < clipHeight)
278       canvasHeight = clipHeight;
279 
280    XtVaSetValues (_drawArea, XmNwidth, canvasWidth, XmNheight, canvasHeight, NULL);
281 }
282 
283 // _clipResizeCallback
284 
_clipResizeCallback(Widget,XtPointer clientData,XtPointer callData)285 void XsMDICanvas::_clipResizeCallback (Widget, XtPointer clientData, XtPointer callData)
286 {
287    XsMDICanvas *obj = (XsMDICanvas*)clientData;
288    obj->_resize (callData);
289 }
290 
291 // _canvasResizeCallback
292 
_canvasResizeCallback(Widget,XtPointer clientData,XtPointer callData)293 void XsMDICanvas::_canvasResizeCallback (Widget, XtPointer clientData, XtPointer callData)
294 {
295    XsMDICanvas *obj = (XsMDICanvas*)clientData;
296    obj->_resize (callData);
297 }
298 
299