xref: /titanic_41/usr/src/cmd/krb5/kadmin/gui/visualrt/sunsoft/jws/visual/rt/awt/TabbedFolder.java (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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  * @(#) TabbedFolder.java 1.20 - last change made 08/04/97
34  */
35 
36 package sunsoft.jws.visual.rt.awt;
37 
38 import sunsoft.jws.visual.rt.base.Global;
39 
40 import java.awt.*;
41 import java.util.*;
42 
43 public class TabbedFolder extends CardPanel {
44 
45     public static final int CONFIRM_SWITCH = 4862;
46 
47     //
48     // Constants used for drawing the tabs
49     //
50 
51     private static final int bd = 2;
52     private static final double BFACTOR = 0.8;
53     private static final double DFACTOR = 0.7;
54 
55     private static final int tabipadx = 14;
56     private static final int tabipady = 14;
57     private static final int comppadx = 20;
58     private static final int comppady = 14;
59     private static final Insets folderInsets = new Insets(6, 6, 6, 6);
60 
61     //
62     // Cached tab information
63     //
64 
65     private Image buffer;
66     private int tabx[];
67     private String tabtext[];
68     private int tabW, tabH;
69     private boolean cancelSwitch = false;
70 
71 
TabbedFolder()72     public TabbedFolder() {
73     }
74 
TabbedFolder(String tabs[])75     public TabbedFolder(String tabs[]) {
76         for (int i = 0; i < tabs.length; i++) {
77             super.addTab(tabs[i]);
78         }
79     }
80 
newCardLabel()81     protected Label newCardLabel() {
82         return new Label(Global.getMsg(
83 		"sunsoft.jws.visual.rt.awt.TabbedFolder.NewCardLabel"));
84     }
85 
86     //
87     // Methods that comprise the public interface for TabbedFolder
88     //
89 
addTab(String tab)90     public void addTab(String tab) {
91         super.addTab(tab);
92         flushCache();
93         repaint();
94     }
95 
addTab(String tab, int index)96     public void addTab(String tab, int index) {
97         super.addTab(tab, index);
98         flushCache();
99         repaint();
100     }
101 
renameTab(String oldName, String newName)102     public void renameTab(String oldName, String newName) {
103         super.renameTab(oldName, newName);
104         flushCache();
105         repaint();
106     }
107 
removeTab(String tab)108     public void removeTab(String tab) {
109         super.removeTab(tab);
110         flushCache();
111         repaint();
112     }
113 
removeAllTabs()114     public void removeAllTabs() {
115         super.removeAllTabs();
116         flushCache();
117         repaint();
118     }
119 
getCurrentFolder()120     public String getCurrentFolder() {
121         return getCurrentCard();
122     }
123 
show(String tab)124     public void show(String tab) {
125         super.show(tab);
126         repaint();
127     }
128 
129     //
130     // Overridden methods from Component
131     //
132 
addNotify()133     public void addNotify() {
134         super.addNotify();
135         flushCache();
136     }
137 
removeNotify()138     public void removeNotify() {
139         super.removeNotify();
140         flushCache();
141     }
142 
setFont(Font font)143     public void setFont(Font font) {
144         super.setFont(font);
145         flushCache();
146     }
147 
minimumSize()148     public Dimension minimumSize() {
149         cacheTabInfo();
150 
151         Dimension d = super.minimumSize();
152         int w = tabW + folderInsets.left + folderInsets.right;
153         if (w > d.width)
154             d = new Dimension(w, d.height);
155 
156         return d;
157     }
158 
preferredSize()159     public Dimension preferredSize() {
160         cacheTabInfo();
161 
162         Dimension d = super.preferredSize();
163         int w = tabW + folderInsets.left + folderInsets.right;
164         if (w > d.width)
165             d = new Dimension(w, d.height);
166 
167         return d;
168     }
169 
insets()170     public Insets insets() {
171         cacheTabInfo();
172 
173         Insets insets = new Insets(0, 0, 0, 0);
174         insets.left = folderInsets.left + bd + comppadx/2;
175         insets.right = folderInsets.right + bd + comppadx/2;
176         insets.top = folderInsets.top + tabH + comppady/2;
177         insets.bottom = folderInsets.bottom + bd + comppady/2;
178 
179         return insets;
180     }
181 
182     //
183     // Event Handling
184     //
185 
mouseDown(Event evt, int x, int y)186     public boolean mouseDown(Event evt, int x, int y) {
187         int index = calcTabIndex(x, y);
188         if (index >= 0 && index < tabs.size()) {
189             String name = (String)tabs.elementAt(index);
190 
191             cancelSwitch = false;
192             postEvent(new Event(this, CONFIRM_SWITCH, name));
193 
194             if (!cancelSwitch) {
195                 show(name);
196                 postEvent(new Event(this, Event.ACTION_EVENT, name));
197             } else {
198                 cancelSwitch = false;
199             }
200         }
201 
202         return false;
203     }
204 
cancelSwitch()205     public void cancelSwitch() {
206         cancelSwitch = true;
207     }
208 
calcTabIndex(int x, int y)209     private synchronized int calcTabIndex(int x, int y) {
210         cacheTabInfo();
211 
212         if (x < (folderInsets.left+tabx[0]) ||
213 	    x > (folderInsets.left+tabx[tabx.length-1])) {
214             return -1;
215         }
216         if (y < (folderInsets.top+bd) || y > (folderInsets.top+tabH)) {
217             return -1;
218         }
219 
220         for (int i = 0; i < tabtext.length; i++) {
221             if (x >= (folderInsets.left+tabx[i]) &&
222 		x <= (folderInsets.left + tabx[i+1])) {
223                 return i;
224             }
225         }
226 
227         return -1;
228     }
229 
230     //
231     // Cache all the information and the image needed for the tabs.
232     //
233 
cacheTabInfo()234     private synchronized void cacheTabInfo() {
235         if (tabx == null) {
236             if (getPeer() == null)
237                 return;
238 
239             FontMetrics fontMetrics = getFontMetrics(getFont());
240             int len = tabs.size();
241 
242             if (len == 0) {
243                 tabx = new int[2];
244                 tabtext = new String[1];
245                 tabtext[0] = Global.getMsg(
246 			   "sunsoft.jws.visual.rt.awt.TabbedFolder.Empty");
247                 tabx[0] = bd;
248                 tabx[1] = tabx[0] +
249 		    fontMetrics.stringWidth(tabtext[0]) + tabipadx + 2*bd;
250             } else {
251                 Enumeration e = tabs.elements();
252                 int i = 0;
253                 int x = bd;
254                 tabx = new int[tabs.size()+1];
255                 tabtext = new String[tabs.size()];
256 
257                 while (e.hasMoreElements()) {
258                     tabtext[i] = (String)e.nextElement();
259                     tabx[i] = x;
260                     x += fontMetrics.stringWidth(tabtext[i]) +
261 			tabipadx + 2*bd;
262                     i++;
263                 }
264                 tabx[i] = x;
265             }
266 
267             // Need 4 extra pixels: 2 on each end
268             tabW = tabx[tabx.length-1] - tabx[0] + 2*bd;
269 
270             // Need 6 extra pixels: 4 on top, and 2 on the bottom
271             tabH = fontMetrics.getMaxAscent() + tabipady + 3*bd;
272 
273             // Create the image buffer
274             buffer = createImage(tabW, tabH);
275         }
276     }
277 
flushCache()278     private synchronized void flushCache() {
279         tabx = null;
280         tabtext = null;
281         tabW = 0;
282         tabH = 0;
283         buffer = null;
284         if (isValid())
285             invalidate();
286     }
287 
288     //
289     // Drawing methods
290     //
291 
update(Graphics g)292     public void update(Graphics g) {
293         if (Global.isWindows())
294             g = getGraphics();
295 
296         cacheTabInfo();
297         Dimension size = size();
298         int x, y;
299 
300         x = folderInsets.left + tabW;
301         y = folderInsets.top + tabH;
302 
303         // Clear the background
304         g.setColor(getBackground());
305         g.fillRect(0, 0, size.width, folderInsets.top);
306         g.fillRect(0, y, size.width, size.height-y);
307         g.fillRect(0, 0, folderInsets.left, size.height);
308         g.fillRect(x, 0, size.width-x, size.height);
309 
310         draw(g);
311     }
312 
paint(Graphics g)313     public void paint(Graphics g) {
314         if (Global.isWindows())
315             g = getGraphics();
316         draw(g);
317     }
318 
draw(Graphics g)319     private synchronized void draw(Graphics g) {
320         cacheTabInfo();
321         Dimension size = size();
322 
323         if (buffer != null) {
324             drawTabs(size);
325             g.drawImage(buffer, folderInsets.left,
326 			folderInsets.top, null);
327         }
328 
329         drawBox(g, size);
330     }
331 
drawTabs(Dimension size)332     private synchronized void drawTabs(Dimension size) {
333         Graphics g = buffer.getGraphics();
334         String card = getCurrentCard();
335         int selIndex = -1;
336         if (card != null)
337             selIndex = tabs.indexOf(card);
338 
339         g.setColor(getBackground());
340         g.fillRect(0, 0, tabW, tabH);
341 
342         for (int i = 0; i < tabtext.length; i++) {
343             if (i != selIndex) {
344                 drawTab(g, i, false);
345             }
346         }
347 
348         for (int i = 0; i < tabtext.length; i++) {
349             if (i == selIndex) {
350                 drawTab(g, i, true);
351                 break;
352             }
353         }
354 
355         // Draw the left extra bit
356         g.setColor(brighter(getBackground()));
357         g.fillRect(0, tabH-bd, bd, bd);
358 
359         // Draw the right extra bit
360         int rightEdge = tabx[tabx.length-1];
361         if ((size.width - tabW) > (folderInsets.left +
362 				   folderInsets.right)) {
363             // The corner does not lie within the image.
364             // This can happen
365             // when the tabs do not completely fill
366             // the top of the folder.
367             g.setColor(brighter(getBackground()));
368             g.fillRect(tabW-bd, tabH-bd, bd, bd);
369         } else {
370             drawUpperRightCorner(g, tabW-bd, tabH-bd);
371         }
372     }
373 
drawUpperRightCorner(Graphics g, int x, int y)374     private void drawUpperRightCorner(Graphics g, int x, int y) {
375         String card = getCurrentCard();
376         int selIndex = -1;
377         if (card != null)
378             selIndex = tabs.indexOf(card);
379 
380         g.setColor(darker(getBackground()));
381         fillRect(g, x, y, bd, bd);
382 
383         int size = tabs.size();
384         if (size == 0 || selIndex != size-1) {
385             g.setColor(brighter(getBackground()));
386             fillRect(g, x, y, 1, 1);
387         }
388     }
389 
drawTab(Graphics g, int index, boolean selected)390     private void drawTab(Graphics g, int index, boolean selected) {
391         int x = tabx[index];
392         int y = bd;
393         int w = tabx[index+1]-tabx[index]-1;
394         int h = tabH-bd-1;
395 
396         if (selected) {
397             x -= bd;
398             y -= bd;
399             w += 2*bd;
400             h += 2*bd;
401         }
402 
403         g.setColor(getBackground());
404         draw3DOuterTab(g, x, y, w, h, selected);
405         draw3DInnerTab(g, x+1, y+1, w-2, h-2, selected);
406 
407         x = tabx[index] + bd + (tabipadx/2);
408         y = tabH - bd - tabipady/2;
409         if (selected)
410             y -= bd;
411 
412         g.setColor(getForeground());
413         g.setFont(getFont());
414         g.drawString(tabtext[index], x, y-1);
415     }
416 
drawBox(Graphics g, Dimension size)417     private void drawBox(Graphics g, Dimension size) {
418         int x = folderInsets.left;
419         int y = folderInsets.top + tabH;
420         int w = size.width - (folderInsets.left +
421 			      folderInsets.right) - 1;
422         int h = size.height - (tabH + folderInsets.top +
423 			       folderInsets.bottom) - 1;
424 
425         if (x >= size.width || y >= size.height || w <= 0 || h <= 0)
426             return;
427 
428         g.setColor(getBackground());
429         draw3DU(g, x, y, w, h, true);
430 
431         // Draw the extra line on the top-right side if the tab image
432         // does not cover the area.  The tab image is only as wide as
433         // the tabs, so we need to account for any possible extra space
434         // here.
435         if ((size.width - tabW) > (folderInsets.left +
436 				   folderInsets.right)) {
437             g.setColor(brighter(getBackground()));
438             fillRect(g, folderInsets.left + tabW,
439 		     folderInsets.top + tabH - bd,
440 		     size.width - (folderInsets.left + folderInsets.right +
441 				   tabW),
442 		     bd);
443             drawUpperRightCorner(g,
444 				 size.width - folderInsets.right - bd,
445 				 folderInsets.top + tabH - bd);
446         }
447     }
448 
draw3DU(Graphics g, int x, int y, int width, int height, boolean raised)449     private void draw3DU(Graphics g, int x, int y, int width,
450 			 int height, boolean raised) {
451         Color c = g.getColor();
452         Color brighter = brighter(c);
453         Color darker = darker(c);
454 
455         g.setColor(raised ? brighter : darker);
456         g.drawLine(x, y, x, y + height);
457         g.drawLine(x+1, y, x+1, y + height);
458 
459         g.setColor(raised ? darker : brighter);
460         g.drawLine(x + 1, y + height, x + width, y + height);
461         g.drawLine(x + 2, y + height - 1, x + width - 1,
462 		   y + height - 1);
463 
464         g.drawLine(x + width, y, x + width, y + height - 1);
465         g.drawLine(x + width - 1, y, x + width - 1, y + height - 1);
466         g.setColor(c);
467     }
468 
draw3DInnerTab(Graphics g, int x, int y, int width, int height, boolean selected)469     private void draw3DInnerTab(Graphics g,
470 				int x, int y, int width, int height,
471 				boolean selected) {
472         Color c = g.getColor();
473         Color brighter = brighter(c);
474         Color darker = darker(c);
475 
476         g.setColor(brighter);
477         g.drawLine(x, y, x, y + height);
478         g.drawLine(x + 1, y, x + width - 1, y);
479         if (!selected)
480             g.drawLine(x + 1, y + height, x + width + 1, y + height);
481         g.setColor(darker);
482         g.drawLine(x + width, y, x + width, y + height - 1);
483         g.setColor(c);
484     }
485 
draw3DOuterTab(Graphics g, int x, int y, int width, int height, boolean selected)486     private void draw3DOuterTab(Graphics g,
487 				int x, int y, int width, int height,
488 				boolean selected) {
489         Color c = g.getColor();
490         Color brighter = brighter(c);
491         Color darker = darker(c);
492 
493         // Left, Top, Bottom, Right
494 
495         g.setColor(brighter);
496         g.drawLine(x, y + 2, x, y + height);
497         g.drawLine(x + 2, y, x + width - 2, y);
498         if (!selected)
499             g.drawLine(x + 1, y + height, x + width, y + height);
500         g.setColor(darker);
501         g.drawLine(x + width, y + 2, x + width, y + height - 2);
502         g.setColor(c);
503     }
504 
505     /**
506      * Returns a brighter version of this color.
507      */
brighter(Color c)508     private Color brighter(Color c) {
509         // fix for bug where the brighter color doesn't show up
510         // against a white background The Util.brighter will return
511         // new Color(<some light grey>) for whites.
512         return Global.util.brighter(c);
513     }
514 
515     /**
516      * Returns a darker version of this color.
517      */
darker(Color c)518     private Color darker(Color c) {
519         return new Color(Math.max((int)(c.getRed()  *DFACTOR), 0),
520 			 Math.max((int)(c.getGreen()*DFACTOR), 0),
521 			 Math.max((int)(c.getBlue() *DFACTOR), 0));
522     }
523 
524     // Workaround for Windows fillRect bug.
525     // The Windows fillRect sometimes
526     // fills the lower-right edges when it shouldn't.
527     // The bug appears to
528     // only happen is certain situations.  It does
529     // not seem to happen when
530     // drawing inside an off-screen buffer.
fillRect(Graphics g, int x, int y, int w, int h)531     private void fillRect(Graphics g, int x, int y, int w, int h) {
532         if (Global.isWindows()) {
533             w -= 1;
534             h -= 1;
535             g.drawRect(x, y, w, h);
536         }
537         g.fillRect(x, y, w, h);
538     }
539 }
540