1 /*
2  * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.java.swing.plaf.motif;
27 
28 import java.awt.Color;
29 import java.awt.Component;
30 import java.awt.Graphics;
31 import java.io.Serializable;
32 
33 import javax.swing.AbstractButton;
34 import javax.swing.ButtonModel;
35 import javax.swing.Icon;
36 import javax.swing.JCheckBox;
37 import javax.swing.UIManager;
38 import javax.swing.plaf.UIResource;
39 
40 /**
41  * Icon factory for the CDE/Motif Look and Feel
42  *
43  * @author Georges Saab
44  */
45 @SuppressWarnings("serial") // Same-version serialization only
46 public class MotifIconFactory implements Serializable
47 {
48     private static Icon checkBoxIcon;
49     private static Icon radioButtonIcon;
50     private static Icon menuItemCheckIcon;
51     private static Icon menuItemArrowIcon;
52     private static Icon menuArrowIcon;
53 
getMenuItemCheckIcon()54     public static Icon getMenuItemCheckIcon() {
55         return null;
56     }
57 
getMenuItemArrowIcon()58     public static Icon getMenuItemArrowIcon() {
59         if (menuItemArrowIcon == null) {
60             menuItemArrowIcon = new MenuItemArrowIcon();
61         }
62         return menuItemArrowIcon;
63     }
64 
getMenuArrowIcon()65     public static Icon getMenuArrowIcon() {
66         if (menuArrowIcon == null) {
67             menuArrowIcon = new MenuArrowIcon();
68         }
69         return menuArrowIcon;
70     }
71 
getCheckBoxIcon()72     public static Icon getCheckBoxIcon() {
73         if (checkBoxIcon == null) {
74             checkBoxIcon = new CheckBoxIcon();
75         }
76         return checkBoxIcon;
77     }
78 
getRadioButtonIcon()79     public static Icon getRadioButtonIcon() {
80         if (radioButtonIcon == null) {
81             radioButtonIcon = new RadioButtonIcon();
82         }
83         return radioButtonIcon;
84     }
85 
86     @SuppressWarnings("serial") // Same-version serialization only
87     private static class CheckBoxIcon implements Icon, UIResource, Serializable  {
88         static final int csize = 13;
89 
90         private Color control = UIManager.getColor("control");
91         private Color foreground = UIManager.getColor("CheckBox.foreground");
92         private Color shadow = UIManager.getColor("controlShadow");
93         private Color highlight = UIManager.getColor("controlHighlight");
94         private Color lightShadow = UIManager.getColor("controlLightShadow");
95 
paintIcon(Component c, Graphics g, int x, int y)96         public void paintIcon(Component c, Graphics g, int x, int y) {
97             AbstractButton b = (AbstractButton) c;
98             ButtonModel model = b.getModel();
99 
100             boolean flat = false;
101 
102             if(b instanceof JCheckBox) {
103                 flat = ((JCheckBox)b).isBorderPaintedFlat();
104             }
105 
106             boolean isPressed = model.isPressed();
107             boolean isArmed = model.isArmed();
108             boolean isEnabled = model.isEnabled();
109             boolean isSelected = model.isSelected();
110 
111             // There are 4 "looks" to the Motif CheckBox:
112             //  drawCheckBezelOut  -  default unchecked state
113             //  drawBezel          -  when we uncheck in toggled state
114             //  drawCheckBezel     -  when we check in toggle state
115             //  drawCheckBezelIn   -  selected, mouseReleased
116             boolean checkToggleIn = ((isPressed &&
117                                       !isArmed   &&
118                                       isSelected) ||
119                                      (isPressed &&
120                                       isArmed   &&
121                                       !isSelected));
122             boolean uncheckToggleOut = ((isPressed &&
123                                          !isArmed &&
124                                          !isSelected) ||
125                                         (isPressed &&
126                                          isArmed &&
127                                          isSelected));
128 
129             boolean checkIn = (!isPressed  &&
130                                isArmed    &&
131                                isSelected  ||
132                                (!isPressed &&
133                                 !isArmed  &&
134                                 isSelected));
135 
136 
137             if(flat) {
138                 g.setColor(shadow);
139                 g.drawRect(x+2,y,csize-1,csize-1);
140                 if(uncheckToggleOut || checkToggleIn) {
141                     g.setColor(control);
142                     g.fillRect(x+3,y+1,csize-2,csize-2);
143                 }
144             }
145 
146             if (checkToggleIn) {
147                 // toggled from unchecked to checked
148                 drawCheckBezel(g,x,y,csize,true,false,false,flat);
149             } else if (uncheckToggleOut) {
150                 // MotifBorderFactory.drawBezel(g,x,y,csize,csize,false,false);
151                 drawCheckBezel(g,x,y,csize,true,true,false,flat);
152             } else if (checkIn) {
153                 // show checked, unpressed state
154                 drawCheckBezel(g,x,y,csize,false,false,true,flat);
155             } else if(!flat) {
156                 //  show unchecked state
157                 drawCheckBezelOut(g,x,y,csize);
158             }
159         }
160 
getIconWidth()161         public int getIconWidth() {
162             return csize;
163         }
164 
getIconHeight()165         public int getIconHeight() {
166             return csize;
167         }
168 
drawCheckBezelOut(Graphics g, int x, int y, int csize)169         public void drawCheckBezelOut(Graphics g, int x, int y, int csize){
170             Color controlShadow = UIManager.getColor("controlShadow");
171 
172             int w = csize;
173             int h = csize;
174             Color oldColor = g.getColor();
175 
176             g.translate(x,y);
177             g.setColor(highlight);    // inner 3D border
178             g.drawLine(0, 0, 0, h-1);
179             g.drawLine(1, 0, w-1, 0);
180 
181             g.setColor(shadow);         // black drop shadow  __|
182             g.drawLine(1, h-1, w-1, h-1);
183             g.drawLine(w-1, h-1, w-1, 1);
184             g.translate(-x,-y);
185             g.setColor(oldColor);
186         }
187 
drawCheckBezel(Graphics g, int x, int y, int csize, boolean shade, boolean out, boolean check, boolean flat)188         public void drawCheckBezel(Graphics g, int x, int y, int csize,
189                                    boolean shade, boolean out, boolean check, boolean flat)
190             {
191 
192 
193                 Color oldColor = g.getColor();
194                 g.translate(x, y);
195 
196 
197                 //bottom
198                 if(!flat) {
199                     if (out) {
200                         g.setColor(control);
201                         g.fillRect(1,1,csize-2,csize-2);
202                         g.setColor(shadow);
203                     } else {
204                         g.setColor(lightShadow);
205                         g.fillRect(0,0,csize,csize);
206                         g.setColor(highlight);
207                     }
208 
209                     g.drawLine(1,csize-1,csize-2,csize-1);
210                     if (shade) {
211                         g.drawLine(2,csize-2,csize-3,csize-2);
212                         g.drawLine(csize-2,2,csize-2 ,csize-1);
213                         if (out) {
214                             g.setColor(highlight);
215                         } else {
216                             g.setColor(shadow);
217                         }
218                         g.drawLine(1,2,1,csize-2);
219                         g.drawLine(1,1,csize-3,1);
220                         if (out) {
221                             g.setColor(shadow);
222                         } else {
223                             g.setColor(highlight);
224                         }
225                     }
226                     //right
227                     g.drawLine(csize-1,1,csize-1,csize-1);
228 
229                     //left
230                     if (out) {
231                         g.setColor(highlight);
232                     } else {
233                         g.setColor(shadow);
234                     }
235                     g.drawLine(0,1,0,csize-1);
236 
237                     //top
238                     g.drawLine(0,0,csize-1,0);
239                 }
240 
241                 if (check) {
242                     // draw check
243                     g.setColor(foreground);
244                     int[] xa = {csize - 12, csize - 8, csize - 7, csize - 4,
245                                 csize - 2, csize - 2, csize - 8, csize - 10,
246                                 csize - 11};
247                     int[] ya = new int[]{6, 10, 10, 4, 2, 1, 7, 5, 5};
248                     g.fillPolygon(xa, ya, 9);
249                 }
250                 g.translate(-x, -y);
251                 g.setColor(oldColor);
252             }
253     } // end class CheckBoxIcon
254 
255     @SuppressWarnings("serial") // Same-version serialization only
256     private static class RadioButtonIcon implements Icon, UIResource, Serializable {
257         private Color dot = UIManager.getColor("activeCaptionBorder");
258         private Color highlight = UIManager.getColor("controlHighlight");
259         private Color shadow = UIManager.getColor("controlShadow");
260 
paintIcon(Component c, Graphics g, int x, int y)261         public void paintIcon(Component c, Graphics g, int x, int y) {
262             // fill interior
263             AbstractButton b = (AbstractButton) c;
264             ButtonModel model = b.getModel();
265 
266             int w = getIconWidth();
267             int h = getIconHeight();
268 
269             boolean isPressed = model.isPressed();
270             boolean isArmed = model.isArmed();
271             boolean isEnabled = model.isEnabled();
272             boolean isSelected = model.isSelected();
273 
274             boolean checkIn = ((isPressed &&
275                                 !isArmed   &&
276                                 isSelected) ||
277                                (isPressed &&
278                                 isArmed   &&
279                                 !isSelected)
280                                ||
281                                (!isPressed  &&
282                                 isArmed    &&
283                                 isSelected  ||
284                                 (!isPressed &&
285                                  !isArmed  &&
286                                  isSelected)));
287 
288             if (checkIn){
289                 g.setColor(shadow);
290                 g.drawArc(x, y, w - 1, h - 1, 45, 180);
291                 g.setColor(highlight);
292                 g.drawArc(x, y, w - 1, h - 1, 45, -180);
293                 g.setColor(dot);
294                 g.fillOval(x + 3, y + 3, 7, 7);
295             }
296             else {
297                 g.setColor(highlight);
298                 g.drawArc(x, y, w - 1, h - 1, 45, 180);
299 
300                 g.setColor(shadow);
301                 g.drawArc(x, y, w - 1, h - 1, 45, -180);
302 
303             }
304         }
305 
getIconWidth()306         public int getIconWidth() {
307             return 14;
308         }
309 
getIconHeight()310         public int getIconHeight() {
311             return 14;
312         }
313     } // end class RadioButtonIcon
314 
315     @SuppressWarnings("serial") // Same-version serialization only
316     private static class MenuItemCheckIcon implements Icon, UIResource, Serializable
317     {
paintIcon(Component c,Graphics g, int x, int y)318         public void paintIcon(Component c,Graphics g, int x, int y)
319             {
320             }
getIconWidth()321         public int getIconWidth() { return 0; }
getIconHeight()322         public int getIconHeight() { return 0; }
323     }  // end class MenuItemCheckIcon
324 
325 
326     @SuppressWarnings("serial") // Same-version serialization only
327     private static class MenuItemArrowIcon implements Icon, UIResource, Serializable
328     {
paintIcon(Component c,Graphics g, int x, int y)329         public void paintIcon(Component c,Graphics g, int x, int y)
330             {
331             }
getIconWidth()332         public int getIconWidth() { return 0; }
getIconHeight()333         public int getIconHeight() { return 0; }
334     }  // end class MenuItemArrowIcon
335 
336     @SuppressWarnings("serial") // Same-version serialization only
337     private static class MenuArrowIcon implements Icon, UIResource, Serializable
338     {
339         private Color focus = UIManager.getColor("windowBorder");
340         private Color shadow = UIManager.getColor("controlShadow");
341         private Color highlight = UIManager.getColor("controlHighlight");
342 
paintIcon(Component c, Graphics g, int x, int y)343         public void paintIcon(Component c, Graphics g, int x, int y) {
344             AbstractButton b = (AbstractButton) c;
345             ButtonModel model = b.getModel();
346 
347             // These variables are kind of pointless as the following code
348             // assumes the icon will be 10 x 10 regardless of their value.
349             int w = getIconWidth();
350             int h = getIconHeight();
351 
352             Color oldColor = g.getColor();
353 
354             if (model.isSelected()){
355                 if (c.getComponentOrientation().isLeftToRight()) {
356                     g.setColor(shadow);
357                     g.fillRect(x+1,y+1,2,h);
358                     g.drawLine(x+4,y+2,x+4,y+2);
359                     g.drawLine(x+6,y+3,x+6,y+3);
360                     g.drawLine(x+8,y+4,x+8,y+5);
361                     g.setColor(focus);
362                     g.fillRect(x+2,y+2,2,h-2);
363                     g.fillRect(x+4,y+3,2,h-4);
364                     g.fillRect(x+6,y+4,2,h-6);
365                     g.setColor(highlight);
366                     g.drawLine(x+2,y+h,x+2,y+h);
367                     g.drawLine(x+4,y+h-1,x+4,y+h-1);
368                     g.drawLine(x+6,y+h-2,x+6,y+h-2);
369                     g.drawLine(x+8,y+h-4,x+8,y+h-3);
370                 } else {
371                     g.setColor(highlight);
372                     g.fillRect(x+7,y+1,2,10);
373                     g.drawLine(x+5,y+9,x+5,y+9);
374                     g.drawLine(x+3,y+8,x+3,y+8);
375                     g.drawLine(x+1,y+6,x+1,y+7);
376                     g.setColor(focus);
377                     g.fillRect(x+6,y+2,2,8);
378                     g.fillRect(x+4,y+3,2,6);
379                     g.fillRect(x+2,y+4,2,4);
380                     g.setColor(shadow);
381                     g.drawLine(x+1,y+4,x+1,y+5);
382                     g.drawLine(x+3,y+3,x+3,y+3);
383                     g.drawLine(x+5,y+2,x+5,y+2);
384                     g.drawLine(x+7,y+1,x+7,y+1);
385                 }
386             } else {
387                 if (c.getComponentOrientation().isLeftToRight()) {
388                     g.setColor(highlight);
389                     g.drawLine(x+1,y+1,x+1,y+h);
390                     g.drawLine(x+2,y+1,x+2,y+h-2);
391                     g.fillRect(x+3,y+2,2,2);
392                     g.fillRect(x+5,y+3,2,2);
393                     g.fillRect(x+7,y+4,2,2);
394                     g.setColor(shadow);
395                     g.drawLine(x+2,y+h-1,x+2,y+h);
396                     g.fillRect(x+3,y+h-2,2,2);
397                     g.fillRect(x+5,y+h-3,2,2);
398                     g.fillRect(x+7,y+h-4,2,2);
399                     g.setColor(oldColor);
400                 } else {
401                     g.setColor(highlight);
402                     g.fillRect(x+1,y+4,2,2);
403                     g.fillRect(x+3,y+3,2,2);
404                     g.fillRect(x+5,y+2,2,2);
405                     g.drawLine(x+7,y+1,x+7,y+2);
406                     g.setColor(shadow);
407                     g.fillRect(x+1,y+h-4,2,2);
408                     g.fillRect(x+3,y+h-3,2,2);
409                     g.fillRect(x+5,y+h-2,2,2);
410                     g.drawLine(x+7,y+3,x+7,y+h);
411                     g.drawLine(x+8,y+1,x+8,y+h);
412                     g.setColor(oldColor);
413                 }
414             }
415 
416         }
getIconWidth()417         public int getIconWidth() { return 10; }
getIconHeight()418         public int getIconHeight() { return 10; }
419     } // End class MenuArrowIcon
420 }
421