1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * ident	"%Z%%M%	%I%	%E% SMI"
24 *
25 * Copyright (c) 2000 by Sun Microsystems, Inc.
26 * All rights reserved.
27 */
28
29/*
30 *        Copyright (C) 1996  Active Software, Inc.
31 *                  All rights reserved.
32 *
33 * @(#) ScrollPanel.java 1.41 - last change made 07/25/97
34 */
35
36package sunsoft.jws.visual.rt.awt;
37
38import sunsoft.jws.visual.rt.awt.*;
39import sunsoft.jws.visual.rt.base.Global;
40import sunsoft.jws.visual.rt.base.Util;
41import java.awt.*;
42
43public class ScrollPanel extends VJPanel {
44    protected VJScrollbar vbar, hbar;
45
46    private Component comp;
47    private boolean vshow, hshow;
48    private GBLayout gridbag;
49    private boolean hasFocus;
50
51    private int scrollAreaWidth = 0;
52    private int scrollAreaHeight = 0;
53    private Insets scrollAreaInsets;
54
55    public ScrollPanel() {
56        super(Util.WIN95_FIELD_BORDER);
57        setBorderInsets(new Insets(0, 0, 0, 0));
58
59        GBConstraints c = new GBConstraints();
60        gridbag = new GBLayout();
61        setLayout(gridbag);
62
63        hbar = new VJScrollbar(VJScrollbar.HORIZONTAL);
64        vbar = new VJScrollbar(VJScrollbar.VERTICAL);
65
66        c.gridx = 1;
67        c.gridy = 0;
68        c.shrinkx = false;
69        c.shrinky = true;
70        c.fill = GBConstraints.VERTICAL;
71
72        // #ifdef JDK1.1
73        super.addImpl(vbar, null, -1);
74        // #else
75	// super.add(vbar, -1);
76        // #endif
77
78        gridbag.setConstraints(vbar, c);
79
80        c.gridx = 0;
81        c.gridy = 1;
82        c.shrinkx = true;
83        c.shrinky = false;
84        c.fill = GBConstraints.HORIZONTAL;
85
86        // #ifdef JDK1.1
87        super.addImpl(hbar, null, -1);
88        // #else
89	// super.add(hbar, -1);
90        // #endif
91
92        gridbag.setConstraints(hbar, c);
93
94        // Have the initial minimumSize include the vertical scrollbar,
95        // but not the horizontal scrollbar.
96        vshow = true;
97        hbar.hide();
98    }
99
100    // #ifdef JDK1.1
101    protected void addImpl(Component comp, Object constraints,
102			   int index) {
103        super.addImpl(comp, constraints, index);
104        doAdd(comp);
105    }
106    // #else
107    // public Component add(Component comp, int pos) {
108    //   super.add(comp, pos);
109    //   doAdd(comp);
110    //   return comp;
111    // }
112    // #endif
113
114    private void doAdd(Component comp) {
115        if (!(comp instanceof Scrollable))
116            throw new Error(Global.getMsg(
117		  "sunsoft.jws.visual.rt.awt.ScrollPanel.OnlyOneInstance"));
118
119        if (this.comp != null)
120            remove(this.comp);
121
122        this.comp = comp;
123
124        GBConstraints c = new GBConstraints();
125        c.gridx = 0;
126        c.gridy = 0;
127        c.weightx = 1;
128        c.weighty = 1;
129        c.shrinkx = true;
130        c.shrinky = true;
131        c.fill = GBConstraints.BOTH;
132        c.insets = scrollAreaInsets;
133
134        gridbag.setConstraints(comp, c);
135    }
136
137    public int getScrollAreaWidth() {
138        return scrollAreaWidth;
139    }
140
141    public void setScrollAreaWidth(int scrollAreaWidth) {
142        this.scrollAreaWidth = scrollAreaWidth;
143    }
144
145    public int getScrollAreaHeight() {
146        return scrollAreaHeight;
147    }
148
149    public void setScrollAreaHeight(int scrollAreaHeight) {
150        this.scrollAreaHeight = scrollAreaHeight;
151    }
152
153    public Insets getScrollAreaInsets() {
154        return scrollAreaInsets;
155    }
156
157    public void setScrollAreaInsets(Insets insets) {
158        scrollAreaInsets = insets;
159
160        if (comp != null) {
161            GBConstraints c = gridbag.getConstraints(comp);
162            c.insets = insets;
163            gridbag.setConstraints(comp, c);
164        }
165    }
166
167    public int getVisibleIndex() {
168        if (!vshow)
169            return 0;
170
171        int lineHeight = ((Scrollable)comp).lineHeight();
172        int scrolly = vbar.getValue();
173
174        return (scrolly+lineHeight-1)/lineHeight;
175    }
176
177    public void makeVisible(int index) {
178        if (!vshow)
179            return;
180
181        if (index == -1)
182            return;
183
184        Scrollable scrollable = (Scrollable)comp;
185        Dimension viewSize = scrollable.viewSize(comp.size());
186        int lineHeight = scrollable.lineHeight();
187        int y = lineHeight*index;
188        int scrolly = vbar.getValue();
189
190        if (y < scrolly) {
191            vbar.setValue(y);
192            scrollable.scrollY(y);
193        } else if ((y + lineHeight) > scrolly + viewSize.height) {
194            y -= (viewSize.height - lineHeight);
195            if (y < 0)
196                y = 0;
197            vbar.setValue(y);
198            scrollable.scrollY(y);
199        }
200    }
201
202    public boolean handleEvent(Event e) {
203        if (e.id == Event.GOT_FOCUS) {
204            hasFocus = true;
205            return super.handleEvent(e);
206        } else if (e.id == Event.LOST_FOCUS) {
207            hasFocus = false;
208            return super.handleEvent(e);
209        } else if (e.target == hbar)
210            ((Scrollable)comp).scrollX(hbar.getValue());
211        else if (e.target == vbar)
212            ((Scrollable)comp).scrollY(vbar.getValue());
213        else
214            return super.handleEvent(e);
215
216        return true;
217    }
218
219    private Dimension viewSize() {
220        Dimension size = size();
221        size = new Dimension(size.width, size.height);
222
223        // take out our insets
224        Insets insets = insets();
225        Insets scrollAreaInsets = getScrollAreaInsets();
226        if (scrollAreaInsets == null)
227            scrollAreaInsets = new Insets(0, 0, 0, 0);
228
229        size.width -= (insets.left + insets.right +
230		       scrollAreaInsets.left + scrollAreaInsets.right);
231        size.height -= (insets.top + insets.bottom +
232			scrollAreaInsets.top + scrollAreaInsets.bottom);
233
234        return ((Scrollable)comp).viewSize(size);
235    }
236
237    // Always leave space for the scrollbars
238    public Dimension minimumSize() {
239        Dimension compMin;
240        Dimension hbarMin = hbar.minimumSize();
241        Dimension vbarMin = vbar.minimumSize();
242
243        if (comp != null) {
244            compMin = comp.minimumSize();
245            compMin = new Dimension(compMin.width, compMin.height);
246        }
247        else
248            compMin = new Dimension(0, 0);
249
250        return calcSize(compMin, hbarMin, vbarMin);
251    }
252
253    // Always leave space for the scrollbars
254    public Dimension preferredSize() {
255        Dimension compPref;
256        Dimension hbarPref = hbar.preferredSize();
257        Dimension vbarPref = vbar.preferredSize();
258
259        if (comp != null) {
260            compPref = comp.preferredSize();
261            compPref = new Dimension(compPref.width, compPref.height);
262        }
263        else
264            compPref = new Dimension(0, 0);
265
266        return calcSize(compPref, hbarPref, vbarPref);
267    }
268
269    private Dimension calcSize(Dimension compMin,
270			       Dimension hbarMin, Dimension vbarMin) {
271        Insets insets = insets();
272        Insets scrollAreaInsets = getScrollAreaInsets();
273        if (scrollAreaInsets == null)
274            scrollAreaInsets = new Insets(0, 0, 0, 0);
275
276        if (scrollAreaWidth != 0)
277            compMin.width = scrollAreaWidth;
278        if (scrollAreaHeight != 0)
279            compMin.height = scrollAreaHeight;
280
281        int insetsWidth = insets.left + insets.right +
282	    scrollAreaInsets.left + scrollAreaInsets.right;
283        compMin.width += (vbarMin.width + insetsWidth);
284        compMin.width = Math.max(compMin.width, (hbarMin.width +
285						 insetsWidth));
286
287        int insetsHeight = insets.top + insets.bottom +
288	    scrollAreaInsets.top + scrollAreaInsets.bottom;
289        compMin.height += (hbarMin.height + insetsHeight);
290        compMin.height = Math.max(compMin.height, (vbarMin.height +
291						   insetsHeight));
292
293        return compMin;
294    }
295
296    public void layout() {
297        boolean hadFocus = hasFocus;
298
299        Dimension viewSize = viewSize();
300        if (viewSize.width <= 0 || viewSize.height <= 0) {
301            super.layout();
302            return;
303        }
304
305        Dimension d;
306        Dimension scrollSize = ((Scrollable)comp).scrollSize();
307        boolean needHShow = false, needVShow = false;
308        boolean revalidate = false;
309
310        if (viewSize.width < scrollSize.width)
311            needHShow = true;
312        if (viewSize.height < scrollSize.height)
313            needVShow = true;
314
315        if ((needHShow || needVShow) && !(needHShow && needVShow)) {
316            if (needVShow) {
317                d = vbar.minimumSize();
318                if (viewSize.width < (scrollSize.width + d.width))
319                    needHShow = true;
320            } else if (needHShow) {
321                d = hbar.minimumSize();
322                if (viewSize.height < (scrollSize.height + d.height))
323                    needVShow = true;
324            }
325        }
326
327        if (needHShow) {
328            if (!hshow) {
329                hbar.show();
330                hshow = true;
331                revalidate = true;
332            }
333        } else {
334            if (hshow) {
335                hbar.hide();
336                hshow = false;
337                revalidate = true;
338                if (hbar.getValue() != 0)
339                    hbar.setValue(0);
340                ((Scrollable)comp).scrollX(0);
341            }
342        }
343
344        if (needVShow) {
345            if (!vshow) {
346                vbar.show();
347                vshow = true;
348                revalidate = true;
349            }
350        } else {
351            if (vshow) {
352                vbar.hide();
353                vshow = false;
354                revalidate = true;
355                if (vbar.getValue() != 0)
356                    vbar.setValue(0);
357                ((Scrollable)comp).scrollY(0);
358            }
359        }
360
361        if (hshow)
362            updateHScrollbar();
363        if (vshow)
364            updateVScrollbar();
365
366        if (revalidate) {
367            validate();
368            if (hadFocus && Global.isMotif())
369                comp.requestFocus();
370        } else {
371            super.layout();
372        }
373    }
374
375    public void updateWindow() {
376        invalidate();
377        validate();
378    }
379
380    protected void updateHScrollbar() {
381        Dimension viewSize = viewSize();
382        Dimension scrollSize = ((Scrollable)comp).scrollSize();
383
384        if (vshow) {
385            Dimension d = vbar.minimumSize();
386            viewSize.width -= d.width;
387        }
388
389        // (viewSize.width-d.width) can become negative
390        // during initialization
391        if (viewSize.width < 1)
392            return;
393
394        int maximum = scrollSize.width;
395        // #ifndef MAXIMUM_HACK
396        // maximum -= viewSize.width;
397        // #endif
398
399        hbar.setValues(hbar.getValue(), viewSize.width, 0, maximum);
400
401        Scrollable scrollable = (Scrollable)comp;
402        int lineWidth = Math.max(10, viewSize.width/6);
403        int pageSize = Math.max(lineWidth, viewSize.width - lineWidth);
404        pageSize = Math.min(scrollSize.width - viewSize.width,
405			    pageSize);
406
407        hbar.setLineIncrement(lineWidth);
408        hbar.setPageIncrement(pageSize);
409
410        scrollable.scrollX(hbar.getValue());
411    }
412
413    protected void updateVScrollbar() {
414        Dimension viewSize = viewSize();
415        Dimension scrollSize = ((Scrollable)comp).scrollSize();
416
417        if (hshow) {
418            Dimension d = hbar.minimumSize();
419            viewSize.height -= d.height;
420        }
421
422        // (viewSize.height-d.height) can become
423        // negative during initialization
424        if (viewSize.height < 1)
425            return;
426
427        int maximum = scrollSize.height;
428        // #ifndef MAXIMUM_HACK
429        // maximum -= viewSize.height;
430        // #endif
431        vbar.setValues(vbar.getValue(), viewSize.height, 0, maximum);
432
433        Scrollable scrollable = (Scrollable)comp;
434        int lineHeight = scrollable.lineHeight();
435        int pageSize =
436	    Math.max(lineHeight,
437		     (viewSize.height/lineHeight)*lineHeight - lineHeight);
438        pageSize = Math.min(scrollSize.height-viewSize.height,
439			    pageSize);
440
441        vbar.setLineIncrement(lineHeight);
442        vbar.setPageIncrement(pageSize);
443
444        scrollable.scrollY(vbar.getValue());
445    }
446}
447