1 /*
2 * Copyright (c) 2002, 2012, 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 package com.sun.java.swing.plaf.gtk;
26
27 import sun.awt.UNIXToolkit;
28
29 import javax.swing.plaf.synth.*;
30 import java.awt.*;
31 import javax.swing.*;
32 import javax.swing.border.*;
33 import javax.swing.plaf.*;
34 import com.sun.java.swing.plaf.gtk.GTKConstants.ArrowType;
35 import com.sun.java.swing.plaf.gtk.GTKConstants.ExpanderStyle;
36 import com.sun.java.swing.plaf.gtk.GTKConstants.Orientation;
37 import com.sun.java.swing.plaf.gtk.GTKConstants.PositionType;
38 import com.sun.java.swing.plaf.gtk.GTKConstants.ShadowType;
39 import java.lang.reflect.InvocationTargetException;
40 import java.lang.reflect.Method;
41
42 /**
43 * @author Joshua Outwater
44 * @author Scott Violet
45 */
46 // Need to support:
47 // default_outside_border: Insets when default.
48 // interior_focus: Indicates if focus should appear inside border, or
49 // outside border.
50 // focus-line-width: Integer giving size of focus border
51 // focus-padding: Integer giving padding between border and focus
52 // indicator.
53 // focus-line-pattern:
54 //
55 class GTKPainter extends SynthPainter {
56 private static final PositionType[] POSITIONS = {
57 PositionType.BOTTOM, PositionType.RIGHT,
58 PositionType.TOP, PositionType.LEFT
550 if (gtkState == SynthConstants.MOUSE_OVER) {
551 Region id = Region.MENU_ITEM;
552 synchronized (UNIXToolkit.GTK_LOCK) {
553 if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
554 ShadowType shadow = (GTKLookAndFeel.is2_2() ?
555 ShadowType.NONE : ShadowType.OUT);
556 ENGINE.startPainting(g, x, y, w, h, id);
557 ENGINE.paintBox(g, context, id, gtkState, shadow,
558 "menuitem", x, y, w, h);
559 ENGINE.finishPainting();
560 }
561 }
562 }
563 }
564
565 public void paintPopupMenuBackground(SynthContext context, Graphics g,
566 int x, int y, int w, int h) {
567 Region id = context.getRegion();
568 int gtkState = GTKLookAndFeel.synthStateToGTKState(
569 id, context.getComponentState());
570 synchronized (UNIXToolkit.GTK_LOCK) {
571 if (ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState)) {
572 return;
573 }
574 ENGINE.startPainting(g, x, y, w, h, id, gtkState);
575 ENGINE.paintBox(g, context, id, gtkState,
576 ShadowType.OUT, "menu", x, y, w, h);
577
578 GTKStyle style = (GTKStyle)context.getStyle();
579 int xThickness = style.getXThickness();
580 int yThickness = style.getYThickness();
581 ENGINE.paintBackground(g, context, id, gtkState,
582 style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND),
583 x + xThickness, y + yThickness,
584 w - xThickness - xThickness, h - yThickness - yThickness);
585 ENGINE.finishPainting();
586 }
587 }
588
589 public void paintProgressBarBackground(SynthContext context,
590 Graphics g,
591 int x, int y, int w, int h) {
592 Region id = context.getRegion();
593 synchronized (UNIXToolkit.GTK_LOCK) {
594 if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
595 ENGINE.startPainting(g, x, y, w, h, id);
596 ENGINE.paintBox(g, context, id, SynthConstants.ENABLED,
597 ShadowType.IN, "trough", x, y, w, h);
598 ENGINE.finishPainting();
599 }
600 }
601 }
602
603 public void paintProgressBarForeground(SynthContext context, Graphics g,
604 int x, int y, int w, int h,
605 int orientation) {
682 if (orientation == JSeparator.HORIZONTAL) {
683 x += (int)(w * pct);
684 w -= (int)(w * pct * 2);
685 y += (size.height - style.getYThickness()) / 2;
686 } else {
687 y += (int)(h * pct);
688 h -= (int)(h * pct * 2);
689 x += (size.width - style.getXThickness()) / 2;
690 }
691 } else {
692 // For regular/menu separators, we simply subtract out the insets.
693 detail = "separator";
694 Insets insets = c.getInsets();
695 x += insets.left;
696 y += insets.top;
697 if (orientation == JSeparator.HORIZONTAL) {
698 w -= (insets.left + insets.right);
699 } else {
700 h -= (insets.top + insets.bottom);
701 }
702 }
703
704 synchronized (UNIXToolkit.GTK_LOCK) {
705 if (! ENGINE.paintCachedImage(g, x, y, w, h, id,
706 state, detail, orientation)) {
707 ENGINE.startPainting(g, x, y, w, h, id,
708 state, detail, orientation);
709 if (orientation == JSeparator.HORIZONTAL) {
710 ENGINE.paintHline(g, context, id, state,
711 detail, x, y, w, h);
712 } else {
713 ENGINE.paintVline(g, context, id, state,
714 detail, x, y, w, h);
715 }
716 ENGINE.finishPainting();
717 }
718 }
719 }
720
721 public void paintSliderTrackBackground(SynthContext context,
726
727 // For focused sliders, we paint focus rect outside the bounds passed.
728 // Need to adjust for that.
729 boolean focused = ((state & SynthConstants.FOCUSED) != 0);
730 int focusSize = 0;
731 if (focused) {
732 GTKStyle style = (GTKStyle)context.getStyle();
733 focusSize = style.getClassSpecificIntValue(
734 context, "focus-line-width", 1) +
735 style.getClassSpecificIntValue(
736 context, "focus-padding", 1);
737 x -= focusSize;
738 y -= focusSize;
739 w += focusSize * 2;
740 h += focusSize * 2;
741 }
742
743 // The ubuntulooks engine paints slider troughs differently depending
744 // on the current slider value and its component orientation.
745 JSlider slider = (JSlider)context.getComponent();
746 double value = slider.getValue();
747 double min = slider.getMinimum();
748 double max = slider.getMaximum();
749 double visible = 20; // not used for sliders; any value will work
750
751 synchronized (UNIXToolkit.GTK_LOCK) {
752 // Note that we don't call paintCachedImage() here. Since some
753 // engines (e.g. ubuntulooks) paint the slider background
754 // differently for any given slider value, it would be wasteful
755 // to try to cache an image for each state, so instead we simply
756 // avoid caching in this case.
757 if (w <= 0 || h <= 0) {
758 return;
759 }
760 ENGINE.startPainting(g, x, y, w, h, id, state, value);
761 int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
762 ENGINE.setRangeValue(context, id, value, min, max, visible);
763 ENGINE.paintBox(g, context, id, gtkState, ShadowType.IN,
764 "trough", x + focusSize, y + focusSize,
765 w - 2 * focusSize, h - 2 * focusSize);
766 if (focused) {
767 ENGINE.paintFocus(g, context, id, SynthConstants.ENABLED,
768 "trough", x, y, w, h);
769 }
770 ENGINE.finishPainting(false); // don't bother caching the image
771 }
772 }
773
774 public void paintSliderThumbBackground(SynthContext context,
775 Graphics g, int x, int y, int w, int h, int dir) {
776 Region id = context.getRegion();
777 int gtkState = GTKLookAndFeel.synthStateToGTKState(
778 id, context.getComponentState());
779 synchronized (UNIXToolkit.GTK_LOCK) {
780 if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir)) {
781 Orientation orientation = (dir == JSlider.HORIZONTAL ?
782 Orientation.HORIZONTAL : Orientation.VERTICAL);
783 String detail = (dir == JSlider.HORIZONTAL ?
784 "hscale" : "vscale");
785 ENGINE.startPainting(g, x, y, w, h, id, gtkState, dir);
786 ENGINE.paintSlider(g, context, id, gtkState,
787 ShadowType.OUT, detail, x, y, w, h, orientation);
788 ENGINE.finishPainting();
789 }
790 }
791 }
792
793 //
794 // SPINNER
795 //
796 public void paintSpinnerBackground(SynthContext context,
797 Graphics g,
798 int x, int y, int w, int h) {
799 // This is handled in paintTextFieldBackground
800 }
801
802 //
803 // SPLIT_PANE_DIVIDER
804 //
805 public void paintSplitPaneDividerBackground(SynthContext context,
806 Graphics g,
807 int x, int y, int w, int h) {
946 }
947
948 int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
949 int focusSize = 0;
950 boolean interiorFocus = style.getClassSpecificBoolValue(
951 context, "interior-focus", true);
952
953 focusSize = style.getClassSpecificIntValue(context,
954 "focus-line-width",1);
955 if (!interiorFocus && (state & SynthConstants.FOCUSED) != 0) {
956 x += focusSize;
957 y += focusSize;
958 w -= 2 * focusSize;
959 h -= 2 * focusSize;
960 }
961
962 int xThickness = style.getXThickness();
963 int yThickness = style.getYThickness();
964
965 ENGINE.startPainting(g, x, y, w, h, id, state);
966 ENGINE.paintShadow(g, context, id, gtkState,
967 ShadowType.IN, "entry", x, y, w, h);
968 ENGINE.paintFlatBox(g, context, id,
969 gtkState, ShadowType.NONE, "entry_bg",
970 x + xThickness,
971 y + yThickness,
972 w - (2 * xThickness),
973 h - (2 * yThickness),
974 ColorType.TEXT_BACKGROUND);
975
976 if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) {
977 if (!interiorFocus) {
978 x -= focusSize;
979 y -= focusSize;
980 w += 2 * focusSize;
981 h += 2 * focusSize;
982 } else {
983 if (containerParent instanceof JComboBox) {
984 x += (focusSize + 2);
985 y += (focusSize + 1);
986 w -= (2 * focusSize + 1);
987 h -= (2 * focusSize + 2);
988 } else {
989 x += focusSize;
990 y += focusSize;
991 w -= 2 * focusSize;
992 h -= 2 * focusSize;
993 }
994 }
995 ENGINE.paintFocus(g, context, id, gtkState,
996 "entry", x, y, w, h);
997 }
998 ENGINE.finishPainting();
999 }
1000 }
1001
1002 private void paintTreeCellEditorBackground(SynthContext context, Graphics g,
1003 int x, int y, int w, int h) {
1004 Region id = context.getRegion();
1005 int gtkState = GTKLookAndFeel.synthStateToGTKState(
1006 id, context.getComponentState());
1007 synchronized (UNIXToolkit.GTK_LOCK) {
1008 if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState)) {
1009 ENGINE.startPainting(g, x, y, w, h, id, gtkState);
1010 ENGINE.paintFlatBox(g, context, id, gtkState, ShadowType.NONE,
1011 "entry_bg", x, y, w, h, ColorType.TEXT_BACKGROUND);
1012 ENGINE.finishPainting();
1122 // At minimum
1123 value = rtl ? 100 : 0;
1124 } else if (sb.getValue() >= sb.getMaximum() - sb.getVisibleAmount()) {
1125 // At maximum
1126 value = rtl ? 0 : 100;
1127 } else {
1128 // Somewhere in between
1129 value = 50;
1130 }
1131
1132 synchronized (UNIXToolkit.GTK_LOCK) {
1133 if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState,
1134 dir, value, visible, rtl))
1135 {
1136 ENGINE.startPainting(g, x, y, w, h, id, gtkState,
1137 dir, value, visible, rtl);
1138 Orientation orientation = (dir == JScrollBar.HORIZONTAL ?
1139 Orientation.HORIZONTAL : Orientation.VERTICAL);
1140 ENGINE.setRangeValue(context, id, value, min, max, visible);
1141 ENGINE.paintSlider(g, context, id, gtkState,
1142 ShadowType.OUT, "slider", x, y, w, h, orientation);
1143 ENGINE.finishPainting();
1144 }
1145 }
1146 }
1147
1148 //
1149 // TOOL_TIP
1150 //
1151 public void paintToolTipBackground(SynthContext context, Graphics g,
1152 int x, int y, int w,int h) {
1153 Region id = context.getRegion();
1154 synchronized (UNIXToolkit.GTK_LOCK) {
1155 if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
1156 ENGINE.startPainting(g, x, y, w, h, id);
1157 ENGINE.paintFlatBox(g, context, id, SynthConstants.ENABLED,
1158 ShadowType.OUT, "tooltip", x, y, w, h,
1159 ColorType.BACKGROUND);
1160 ENGINE.finishPainting();
1161 }
1162 }
1278 x, y, w, h, state, paintMethod, direction);
1279 try {
1280 paintMethod.invoke(this, context,
1281 g, state, x, y, w, h, direction);
1282 } catch (IllegalAccessException iae) {
1283 assert false;
1284 } catch (InvocationTargetException ite) {
1285 assert false;
1286 }
1287 ENGINE.finishPainting();
1288 }
1289 }
1290 }
1291
1292 // All icon painting methods are called from under GTK_LOCK
1293
1294 public void paintTreeExpandedIcon(SynthContext context,
1295 Graphics g, int state, int x, int y, int w, int h) {
1296 ENGINE.paintExpander(g, context, Region.TREE,
1297 GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
1298 ExpanderStyle.EXPANDED, "treeview", x, y, w, h);
1299 }
1300
1301 public void paintTreeCollapsedIcon(SynthContext context,
1302 Graphics g, int state, int x, int y, int w, int h) {
1303 ENGINE.paintExpander(g, context, Region.TREE,
1304 GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
1305 ExpanderStyle.COLLAPSED, "treeview", x, y, w, h);
1306 }
1307
1308 public void paintCheckBoxIcon(SynthContext context,
1309 Graphics g, int state, int x, int y, int w, int h) {
1310 GTKStyle style = (GTKStyle)context.getStyle();
1311 int size = style.getClassSpecificIntValue(context,
1312 "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE);
1313 int offset = style.getClassSpecificIntValue(context,
1314 "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING);
1315
1316 ENGINE.paintCheck(g, context, Region.CHECK_BOX, "checkbutton",
1317 x+offset, y+offset, size, size);
1318 }
1319
1320 public void paintRadioButtonIcon(SynthContext context,
1321 Graphics g, int state, int x, int y, int w, int h) {
1322 GTKStyle style = (GTKStyle)context.getStyle();
1323 int size = style.getClassSpecificIntValue(context,
1324 "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE);
1325 int offset = style.getClassSpecificIntValue(context,
1326 "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING);
1327
1328 ENGINE.paintOption(g, context, Region.RADIO_BUTTON, "radiobutton",
1329 x+offset, y+offset, size, size);
1330 }
1331
1332 public void paintMenuArrowIcon(SynthContext context, Graphics g,
1333 int state, int x, int y, int w, int h, ArrowType dir) {
1334 int gtkState = GTKLookAndFeel.synthStateToGTKState(
1335 context.getRegion(), state);
1336 ShadowType shadow = ShadowType.OUT;
1337 if (gtkState == SynthConstants.MOUSE_OVER) {
1338 shadow = ShadowType.IN;
1339 }
1340 ENGINE.paintArrow(g, context, Region.MENU_ITEM, gtkState, shadow,
1341 dir, "menuitem", x + 3, y + 3, 7, 7);
1342 }
1343
1344 public void paintCheckBoxMenuItemCheckIcon(SynthContext context,
1345 Graphics g, int state, int x, int y, int w, int h) {
1346
1347 GTKStyle style = (GTKStyle)context.getStyle();
1348 int size = style.getClassSpecificIntValue(context,"indicator-size",
1349 GTKIconFactory.DEFAULT_TOGGLE_MENU_ITEM_SIZE);
1350
1351 ENGINE.paintCheck(g, context, Region.CHECK_BOX_MENU_ITEM, "check",
1352 x + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
1353 y + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
1354 size, size);
1355 }
1356
1357 public void paintRadioButtonMenuItemCheckIcon(SynthContext context,
1358 Graphics g, int state, int x, int y, int w, int h) {
1359
1360 GTKStyle style = (GTKStyle)context.getStyle();
1361 int size = style.getClassSpecificIntValue(context,"indicator-size",
|
1 /*
2 * Copyright (c) 2002, 2018, 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 package com.sun.java.swing.plaf.gtk;
26
27 import sun.awt.UNIXToolkit;
28
29 import sun.awt.ModalExclude;
30 import sun.awt.SunToolkit;
31 import javax.swing.plaf.synth.*;
32 import java.awt.*;
33 import javax.swing.*;
34 import javax.swing.border.*;
35 import javax.swing.plaf.*;
36 import com.sun.java.swing.plaf.gtk.GTKConstants.ArrowType;
37 import com.sun.java.swing.plaf.gtk.GTKConstants.ExpanderStyle;
38 import com.sun.java.swing.plaf.gtk.GTKConstants.Orientation;
39 import com.sun.java.swing.plaf.gtk.GTKConstants.PositionType;
40 import com.sun.java.swing.plaf.gtk.GTKConstants.ShadowType;
41 import java.awt.image.BufferedImage;
42 import java.lang.reflect.InvocationTargetException;
43 import java.lang.reflect.Method;
44
45 /**
46 * @author Joshua Outwater
47 * @author Scott Violet
48 */
49 // Need to support:
50 // default_outside_border: Insets when default.
51 // interior_focus: Indicates if focus should appear inside border, or
52 // outside border.
53 // focus-line-width: Integer giving size of focus border
54 // focus-padding: Integer giving padding between border and focus
55 // indicator.
56 // focus-line-pattern:
57 //
58 class GTKPainter extends SynthPainter {
59 private static final PositionType[] POSITIONS = {
60 PositionType.BOTTOM, PositionType.RIGHT,
61 PositionType.TOP, PositionType.LEFT
553 if (gtkState == SynthConstants.MOUSE_OVER) {
554 Region id = Region.MENU_ITEM;
555 synchronized (UNIXToolkit.GTK_LOCK) {
556 if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
557 ShadowType shadow = (GTKLookAndFeel.is2_2() ?
558 ShadowType.NONE : ShadowType.OUT);
559 ENGINE.startPainting(g, x, y, w, h, id);
560 ENGINE.paintBox(g, context, id, gtkState, shadow,
561 "menuitem", x, y, w, h);
562 ENGINE.finishPainting();
563 }
564 }
565 }
566 }
567
568 public void paintPopupMenuBackground(SynthContext context, Graphics g,
569 int x, int y, int w, int h) {
570 Region id = context.getRegion();
571 int gtkState = GTKLookAndFeel.synthStateToGTKState(
572 id, context.getComponentState());
573 boolean isHW = SunToolkit.getHeavyweightComponent(
574 context.getComponent()) instanceof ModalExclude;
575 synchronized (UNIXToolkit.GTK_LOCK) {
576 if (ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, isHW)) {
577 return;
578 }
579 ENGINE.startPainting(g, x, y, w, h, id, gtkState);
580 ENGINE.paintBox(g, context, id, gtkState,
581 ShadowType.OUT, "menu", x, y, w, h);
582
583 GTKStyle style = (GTKStyle)context.getStyle();
584 int xThickness = style.getXThickness();
585 int yThickness = style.getYThickness();
586 ENGINE.paintBackground(g, context, id, gtkState,
587 style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND),
588 x + xThickness, y + yThickness,
589 w - xThickness - xThickness, h - yThickness - yThickness);
590 BufferedImage img = ENGINE.finishPainting();
591 if(!isHW) {
592 int border = img.getRGB(0, h / 2);
593 if (img != null && border == img.getRGB(w / 2, h / 2)) {
594 // fix no menu borders in Adwaita theme
595 Graphics g2 = img.getGraphics();
596 Color c = new Color(border);
597 g2.setColor(new Color(Math.max((int) (c.getRed() * 0.8), 0),
598 Math.max((int) (c.getGreen() * 0.8), 0),
599 Math.max((int) (c.getBlue() * 0.8), 0)));
600 g2.drawLine(0, 0, w - 1, 0);
601 g2.drawLine(w - 1, 0, w - 1, h - 1);
602 g2.drawLine(0, h - 1, 0, 1);
603 g2.setColor(c.darker());
604 g2.drawLine(w - 1, h - 1, 0, h - 1);
605 g2.dispose();
606 g.drawImage(img, x, y, null);
607 }
608 }
609 }
610 }
611
612 public void paintProgressBarBackground(SynthContext context,
613 Graphics g,
614 int x, int y, int w, int h) {
615 Region id = context.getRegion();
616 synchronized (UNIXToolkit.GTK_LOCK) {
617 if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
618 ENGINE.startPainting(g, x, y, w, h, id);
619 ENGINE.paintBox(g, context, id, SynthConstants.ENABLED,
620 ShadowType.IN, "trough", x, y, w, h);
621 ENGINE.finishPainting();
622 }
623 }
624 }
625
626 public void paintProgressBarForeground(SynthContext context, Graphics g,
627 int x, int y, int w, int h,
628 int orientation) {
705 if (orientation == JSeparator.HORIZONTAL) {
706 x += (int)(w * pct);
707 w -= (int)(w * pct * 2);
708 y += (size.height - style.getYThickness()) / 2;
709 } else {
710 y += (int)(h * pct);
711 h -= (int)(h * pct * 2);
712 x += (size.width - style.getXThickness()) / 2;
713 }
714 } else {
715 // For regular/menu separators, we simply subtract out the insets.
716 detail = "separator";
717 Insets insets = c.getInsets();
718 x += insets.left;
719 y += insets.top;
720 if (orientation == JSeparator.HORIZONTAL) {
721 w -= (insets.left + insets.right);
722 } else {
723 h -= (insets.top + insets.bottom);
724 }
725 if (GTKLookAndFeel.is3()) {
726 if (id == Region.POPUP_MENU_SEPARATOR) {
727 detail = "menuitem";
728 h -= (insets.top + insets.bottom);
729 } else {
730 detail = "separator";
731 }
732 } else {
733 detail = orientation == JSeparator.HORIZONTAL ?
734 "hseparator" : "vseparator";
735 }
736 }
737
738 synchronized (UNIXToolkit.GTK_LOCK) {
739 if (! ENGINE.paintCachedImage(g, x, y, w, h, id,
740 state, detail, orientation)) {
741 ENGINE.startPainting(g, x, y, w, h, id,
742 state, detail, orientation);
743 if (orientation == JSeparator.HORIZONTAL) {
744 ENGINE.paintHline(g, context, id, state,
745 detail, x, y, w, h);
746 } else {
747 ENGINE.paintVline(g, context, id, state,
748 detail, x, y, w, h);
749 }
750 ENGINE.finishPainting();
751 }
752 }
753 }
754
755 public void paintSliderTrackBackground(SynthContext context,
760
761 // For focused sliders, we paint focus rect outside the bounds passed.
762 // Need to adjust for that.
763 boolean focused = ((state & SynthConstants.FOCUSED) != 0);
764 int focusSize = 0;
765 if (focused) {
766 GTKStyle style = (GTKStyle)context.getStyle();
767 focusSize = style.getClassSpecificIntValue(
768 context, "focus-line-width", 1) +
769 style.getClassSpecificIntValue(
770 context, "focus-padding", 1);
771 x -= focusSize;
772 y -= focusSize;
773 w += focusSize * 2;
774 h += focusSize * 2;
775 }
776
777 // The ubuntulooks engine paints slider troughs differently depending
778 // on the current slider value and its component orientation.
779 JSlider slider = (JSlider)context.getComponent();
780 if (GTKLookAndFeel.is3()) {
781 if (slider.getOrientation() == JSlider.VERTICAL) {
782 y += 1;
783 h -= 2;
784 } else {
785 x += 1;
786 w -= 2;
787 }
788 }
789 double value = slider.getValue();
790 double min = slider.getMinimum();
791 double max = slider.getMaximum();
792 double visible = 20; // not used for sliders; any value will work
793
794 synchronized (UNIXToolkit.GTK_LOCK) {
795 // Note that we don't call paintCachedImage() here. Since some
796 // engines (e.g. ubuntulooks) paint the slider background
797 // differently for any given slider value, it would be wasteful
798 // to try to cache an image for each state, so instead we simply
799 // avoid caching in this case.
800 if (w <= 0 || h <= 0) {
801 return;
802 }
803 ENGINE.startPainting(g, x, y, w, h, id, state, value);
804 int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
805 ENGINE.setRangeValue(context, id, value, min, max, visible);
806 ENGINE.paintBox(g, context, id, gtkState, ShadowType.IN,
807 "trough", x + focusSize, y + focusSize,
808 w - 2 * focusSize, h - 2 * focusSize);
809 if (focused) {
810 ENGINE.paintFocus(g, context, id, SynthConstants.ENABLED,
811 "trough", x, y, w, h);
812 }
813 ENGINE.finishPainting(false); // don't bother caching the image
814 }
815 }
816
817 public void paintSliderThumbBackground(SynthContext context,
818 Graphics g, int x, int y, int w, int h, int dir) {
819 Region id = context.getRegion();
820 int gtkState = GTKLookAndFeel.synthStateToGTKState(
821 id, context.getComponentState());
822 boolean hasFocus = GTKLookAndFeel.is3() &&
823 ((context.getComponentState() & SynthConstants.FOCUSED) != 0);
824 synchronized (UNIXToolkit.GTK_LOCK) {
825 if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir, hasFocus)) {
826 Orientation orientation = (dir == JSlider.HORIZONTAL ?
827 Orientation.HORIZONTAL : Orientation.VERTICAL);
828 String detail = (dir == JSlider.HORIZONTAL ?
829 "hscale" : "vscale");
830 ENGINE.startPainting(g, x, y, w, h, id, gtkState, dir);
831 ENGINE.paintSlider(g, context, id, gtkState,
832 ShadowType.OUT, detail, x, y, w, h, orientation, hasFocus);
833 ENGINE.finishPainting();
834 }
835 }
836 }
837
838 //
839 // SPINNER
840 //
841 public void paintSpinnerBackground(SynthContext context,
842 Graphics g,
843 int x, int y, int w, int h) {
844 // This is handled in paintTextFieldBackground
845 }
846
847 //
848 // SPLIT_PANE_DIVIDER
849 //
850 public void paintSplitPaneDividerBackground(SynthContext context,
851 Graphics g,
852 int x, int y, int w, int h) {
991 }
992
993 int gtkState = GTKLookAndFeel.synthStateToGTKState(id, state);
994 int focusSize = 0;
995 boolean interiorFocus = style.getClassSpecificBoolValue(
996 context, "interior-focus", true);
997
998 focusSize = style.getClassSpecificIntValue(context,
999 "focus-line-width",1);
1000 if (!interiorFocus && (state & SynthConstants.FOCUSED) != 0) {
1001 x += focusSize;
1002 y += focusSize;
1003 w -= 2 * focusSize;
1004 h -= 2 * focusSize;
1005 }
1006
1007 int xThickness = style.getXThickness();
1008 int yThickness = style.getYThickness();
1009
1010 ENGINE.startPainting(g, x, y, w, h, id, state);
1011 if (GTKLookAndFeel.is3()) {
1012 ENGINE.paintBackground(g, context, id, gtkState, null,
1013 x, y, w, h);
1014 }
1015 ENGINE.paintShadow(g, context, id, gtkState,
1016 ShadowType.IN, "entry", x, y, w, h);
1017 if (!GTKLookAndFeel.is3()) {
1018 ENGINE.paintFlatBox(g, context, id,
1019 gtkState, ShadowType.NONE, "entry_bg",
1020 x + xThickness,
1021 y + yThickness,
1022 w - (2 * xThickness),
1023 h - (2 * yThickness),
1024 ColorType.TEXT_BACKGROUND);
1025 }
1026
1027 if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) {
1028 if (!interiorFocus) {
1029 x -= focusSize;
1030 y -= focusSize;
1031 w += 2 * focusSize;
1032 h += 2 * focusSize;
1033 } else {
1034 if (containerParent instanceof JComboBox) {
1035 x += (focusSize + 2);
1036 y += focusSize + (GTKLookAndFeel.is3() ? 3 : 1);
1037 w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 1);
1038 h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 6 : 2);
1039 } else {
1040 x += focusSize + (GTKLookAndFeel.is3() ? 2 : 0);
1041 y += focusSize + (GTKLookAndFeel.is3() ? 2 :0 );
1042 w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0);
1043 h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0);
1044 }
1045 }
1046 ENGINE.paintFocus(g, context, id, gtkState,
1047 "entry", x, y, w, h);
1048 }
1049 ENGINE.finishPainting();
1050 }
1051 }
1052
1053 private void paintTreeCellEditorBackground(SynthContext context, Graphics g,
1054 int x, int y, int w, int h) {
1055 Region id = context.getRegion();
1056 int gtkState = GTKLookAndFeel.synthStateToGTKState(
1057 id, context.getComponentState());
1058 synchronized (UNIXToolkit.GTK_LOCK) {
1059 if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState)) {
1060 ENGINE.startPainting(g, x, y, w, h, id, gtkState);
1061 ENGINE.paintFlatBox(g, context, id, gtkState, ShadowType.NONE,
1062 "entry_bg", x, y, w, h, ColorType.TEXT_BACKGROUND);
1063 ENGINE.finishPainting();
1173 // At minimum
1174 value = rtl ? 100 : 0;
1175 } else if (sb.getValue() >= sb.getMaximum() - sb.getVisibleAmount()) {
1176 // At maximum
1177 value = rtl ? 0 : 100;
1178 } else {
1179 // Somewhere in between
1180 value = 50;
1181 }
1182
1183 synchronized (UNIXToolkit.GTK_LOCK) {
1184 if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState,
1185 dir, value, visible, rtl))
1186 {
1187 ENGINE.startPainting(g, x, y, w, h, id, gtkState,
1188 dir, value, visible, rtl);
1189 Orientation orientation = (dir == JScrollBar.HORIZONTAL ?
1190 Orientation.HORIZONTAL : Orientation.VERTICAL);
1191 ENGINE.setRangeValue(context, id, value, min, max, visible);
1192 ENGINE.paintSlider(g, context, id, gtkState,
1193 ShadowType.OUT, "slider", x, y, w, h, orientation, false);
1194 ENGINE.finishPainting();
1195 }
1196 }
1197 }
1198
1199 //
1200 // TOOL_TIP
1201 //
1202 public void paintToolTipBackground(SynthContext context, Graphics g,
1203 int x, int y, int w,int h) {
1204 Region id = context.getRegion();
1205 synchronized (UNIXToolkit.GTK_LOCK) {
1206 if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
1207 ENGINE.startPainting(g, x, y, w, h, id);
1208 ENGINE.paintFlatBox(g, context, id, SynthConstants.ENABLED,
1209 ShadowType.OUT, "tooltip", x, y, w, h,
1210 ColorType.BACKGROUND);
1211 ENGINE.finishPainting();
1212 }
1213 }
1329 x, y, w, h, state, paintMethod, direction);
1330 try {
1331 paintMethod.invoke(this, context,
1332 g, state, x, y, w, h, direction);
1333 } catch (IllegalAccessException iae) {
1334 assert false;
1335 } catch (InvocationTargetException ite) {
1336 assert false;
1337 }
1338 ENGINE.finishPainting();
1339 }
1340 }
1341 }
1342
1343 // All icon painting methods are called from under GTK_LOCK
1344
1345 public void paintTreeExpandedIcon(SynthContext context,
1346 Graphics g, int state, int x, int y, int w, int h) {
1347 ENGINE.paintExpander(g, context, Region.TREE,
1348 GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
1349 ExpanderStyle.EXPANDED, "expander", x, y, w, h);
1350 }
1351
1352 public void paintTreeCollapsedIcon(SynthContext context,
1353 Graphics g, int state, int x, int y, int w, int h) {
1354 ENGINE.paintExpander(g, context, Region.TREE,
1355 GTKLookAndFeel.synthStateToGTKState(context.getRegion(), state),
1356 ExpanderStyle.COLLAPSED, "expander", x, y, w, h);
1357 }
1358
1359 public void paintCheckBoxIcon(SynthContext context,
1360 Graphics g, int state, int x, int y, int w, int h) {
1361 GTKStyle style = (GTKStyle)context.getStyle();
1362 int size = style.getClassSpecificIntValue(context,
1363 "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE);
1364 int offset = style.getClassSpecificIntValue(context,
1365 "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING);
1366
1367 ENGINE.paintCheck(g, context, Region.CHECK_BOX, "checkbutton",
1368 x+offset, y+offset, size, size);
1369 }
1370
1371 public void paintRadioButtonIcon(SynthContext context,
1372 Graphics g, int state, int x, int y, int w, int h) {
1373 GTKStyle style = (GTKStyle)context.getStyle();
1374 int size = style.getClassSpecificIntValue(context,
1375 "indicator-size", GTKIconFactory.DEFAULT_ICON_SIZE);
1376 int offset = style.getClassSpecificIntValue(context,
1377 "indicator-spacing", GTKIconFactory.DEFAULT_ICON_SPACING);
1378
1379 ENGINE.paintOption(g, context, Region.RADIO_BUTTON, "radiobutton",
1380 x+offset, y+offset, size, size);
1381 }
1382
1383 public void paintMenuArrowIcon(SynthContext context, Graphics g,
1384 int state, int x, int y, int w, int h, ArrowType dir) {
1385 int gtkState = GTKLookAndFeel.synthStateToGTKState(
1386 context.getRegion(), state);
1387 ShadowType shadow = ShadowType.OUT;
1388 if (gtkState == SynthConstants.MOUSE_OVER) {
1389 shadow = ShadowType.IN;
1390 }
1391 if (!GTKLookAndFeel.is3()) {
1392 x += 3;
1393 y += 3;
1394 w = h = 7;
1395 }
1396 ENGINE.paintArrow(g, context, Region.MENU_ITEM, gtkState, shadow,
1397 dir, "menuitem", x, y, w, h);
1398 }
1399
1400 public void paintCheckBoxMenuItemCheckIcon(SynthContext context,
1401 Graphics g, int state, int x, int y, int w, int h) {
1402
1403 GTKStyle style = (GTKStyle)context.getStyle();
1404 int size = style.getClassSpecificIntValue(context,"indicator-size",
1405 GTKIconFactory.DEFAULT_TOGGLE_MENU_ITEM_SIZE);
1406
1407 ENGINE.paintCheck(g, context, Region.CHECK_BOX_MENU_ITEM, "check",
1408 x + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
1409 y + GTKIconFactory.CHECK_ICON_EXTRA_INSET,
1410 size, size);
1411 }
1412
1413 public void paintRadioButtonMenuItemCheckIcon(SynthContext context,
1414 Graphics g, int state, int x, int y, int w, int h) {
1415
1416 GTKStyle style = (GTKStyle)context.getStyle();
1417 int size = style.getClassSpecificIntValue(context,"indicator-size",
|