1 /* 2 * Copyright (c) 2005, 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 26 package com.sun.java.swing.plaf.gtk; 27 28 import java.awt.*; 29 import java.awt.image.*; 30 import java.util.HashMap; 31 import javax.swing.*; 32 import javax.swing.plaf.synth.*; 33 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 com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection; 40 41 import sun.awt.image.SunWritableRaster; 42 import sun.swing.ImageCache; 43 44 /** 45 * GTKEngine delegates all painting job to native GTK libraries. 46 * 47 * Painting with GTKEngine looks like this: 48 * First, startPainting() is called. It prepares an offscreen buffer of the 49 * required size. 50 * Then, any number of paintXXX() methods can be called. They effectively ignore 51 * the Graphics parameter and draw to the offscreen buffer. 52 * Finally, finishPainting() should be called. It fills the data buffer passed 53 * in with the image data. 54 * 55 * @author Josh Outwater 56 */ 57 class GTKEngine { 58 59 final static GTKEngine INSTANCE = new GTKEngine(); 60 61 /** Size of the image cache */ 62 private static final int CACHE_SIZE = 50; 63 64 /** This enum mirrors that in gtk2_interface.h */ 65 static enum WidgetType { 66 BUTTON, CHECK_BOX, CHECK_BOX_MENU_ITEM, COLOR_CHOOSER, 67 COMBO_BOX, COMBO_BOX_ARROW_BUTTON, COMBO_BOX_TEXT_FIELD, 68 DESKTOP_ICON, DESKTOP_PANE, EDITOR_PANE, FORMATTED_TEXT_FIELD, 69 HANDLE_BOX, HPROGRESS_BAR, 70 HSCROLL_BAR, HSCROLL_BAR_BUTTON_LEFT, HSCROLL_BAR_BUTTON_RIGHT, 71 HSCROLL_BAR_TRACK, HSCROLL_BAR_THUMB, 72 HSEPARATOR, HSLIDER, HSLIDER_TRACK, HSLIDER_THUMB, HSPLIT_PANE_DIVIDER, 73 INTERNAL_FRAME, INTERNAL_FRAME_TITLE_PANE, IMAGE, LABEL, LIST, MENU, 74 MENU_BAR, MENU_ITEM, MENU_ITEM_ACCELERATOR, OPTION_PANE, PANEL, 75 PASSWORD_FIELD, POPUP_MENU, POPUP_MENU_SEPARATOR, 76 RADIO_BUTTON, RADIO_BUTTON_MENU_ITEM, ROOT_PANE, SCROLL_PANE, 77 SPINNER, SPINNER_ARROW_BUTTON, SPINNER_TEXT_FIELD, 78 SPLIT_PANE, TABBED_PANE, TABBED_PANE_TAB_AREA, TABBED_PANE_CONTENT, 79 TABBED_PANE_TAB, TABLE, TABLE_HEADER, TEXT_AREA, TEXT_FIELD, TEXT_PANE, 80 TITLED_BORDER, 81 TOGGLE_BUTTON, TOOL_BAR, TOOL_BAR_DRAG_WINDOW, TOOL_BAR_SEPARATOR, 82 TOOL_TIP, TREE, TREE_CELL, VIEWPORT, VPROGRESS_BAR, 83 VSCROLL_BAR, VSCROLL_BAR_BUTTON_UP, VSCROLL_BAR_BUTTON_DOWN, 84 VSCROLL_BAR_TRACK, VSCROLL_BAR_THUMB, 85 VSEPARATOR, VSLIDER, VSLIDER_TRACK, VSLIDER_THUMB, 86 VSPLIT_PANE_DIVIDER 87 } 88 89 /** 90 * Representation of GtkSettings properties. 91 * When we need more settings we can add them here and 92 * to all implementations of getGTKSetting(). 93 */ 94 static enum Settings { 95 GTK_FONT_NAME, 96 GTK_ICON_SIZES, 97 GTK_CURSOR_BLINK, 98 GTK_CURSOR_BLINK_TIME 99 } 100 101 /* Custom regions are needed for representing regions that don't exist 102 * in the original Region class. 103 */ 104 static class CustomRegion extends Region { 105 /* 106 * TITLED_BORDER Region is mapped to GtkFrame class which can draw 107 * titled borders around components. 108 */ 109 static Region TITLED_BORDER = new CustomRegion("TitledBorder"); 110 CustomRegion(String name)111 private CustomRegion(String name) { 112 super(name, null, false); 113 } 114 } 115 116 117 private static HashMap<Region, Object> regionToWidgetTypeMap; 118 private ImageCache cache = new ImageCache(CACHE_SIZE); 119 private int x0, y0, w0, h0; 120 private Graphics graphics; 121 private Object[] cacheArgs; 122 native_paint_arrow( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int arrowType)123 private native void native_paint_arrow( 124 int widgetType, int state, int shadowType, String detail, 125 int x, int y, int width, int height, int arrowType); native_paint_box( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int synthState, int dir)126 private native void native_paint_box( 127 int widgetType, int state, int shadowType, String detail, 128 int x, int y, int width, int height, int synthState, int dir); native_paint_box_gap( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int gapSide, int gapX, int gapWidth)129 private native void native_paint_box_gap( 130 int widgetType, int state, int shadowType, String detail, 131 int x, int y, int width, int height, 132 int gapSide, int gapX, int gapWidth); native_paint_check( int widgetType, int synthState, String detail, int x, int y, int width, int height)133 private native void native_paint_check( 134 int widgetType, int synthState, String detail, 135 int x, int y, int width, int height); native_paint_expander( int widgetType, int state, String detail, int x, int y, int width, int height, int expanderStyle)136 private native void native_paint_expander( 137 int widgetType, int state, String detail, 138 int x, int y, int width, int height, int expanderStyle); native_paint_extension( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int placement)139 private native void native_paint_extension( 140 int widgetType, int state, int shadowType, String detail, 141 int x, int y, int width, int height, int placement); native_paint_flat_box( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, boolean hasFocus)142 private native void native_paint_flat_box( 143 int widgetType, int state, int shadowType, String detail, 144 int x, int y, int width, int height, boolean hasFocus); native_paint_focus( int widgetType, int state, String detail, int x, int y, int width, int height)145 private native void native_paint_focus( 146 int widgetType, int state, String detail, 147 int x, int y, int width, int height); native_paint_handle( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int orientation)148 private native void native_paint_handle( 149 int widgetType, int state, int shadowType, String detail, 150 int x, int y, int width, int height, int orientation); native_paint_hline( int widgetType, int state, String detail, int x, int y, int width, int height)151 private native void native_paint_hline( 152 int widgetType, int state, String detail, 153 int x, int y, int width, int height); native_paint_option( int widgetType, int synthState, String detail, int x, int y, int width, int height)154 private native void native_paint_option( 155 int widgetType, int synthState, String detail, 156 int x, int y, int width, int height); native_paint_shadow( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int synthState, int dir)157 private native void native_paint_shadow( 158 int widgetType, int state, int shadowType, String detail, 159 int x, int y, int width, int height, int synthState, int dir); native_paint_slider( int widgetType, int state, int shadowType, String detail, int x, int y, int width, int height, int orientation, boolean hasFocus)160 private native void native_paint_slider( 161 int widgetType, int state, int shadowType, String detail, int x, 162 int y, int width, int height, int orientation, boolean hasFocus); native_paint_vline( int widgetType, int state, String detail, int x, int y, int width, int height)163 private native void native_paint_vline( 164 int widgetType, int state, String detail, 165 int x, int y, int width, int height); native_paint_background( int widgetType, int state, int x, int y, int width, int height)166 private native void native_paint_background( 167 int widgetType, int state, int x, int y, int width, int height); native_get_gtk_setting(int property)168 private native Object native_get_gtk_setting(int property); nativeSetRangeValue(int widgetType, double value, double min, double max, double visible)169 private native void nativeSetRangeValue(int widgetType, double value, 170 double min, double max, 171 double visible); 172 nativeStartPainting(int w, int h)173 private native void nativeStartPainting(int w, int h); nativeFinishPainting(int[] buffer, int width, int height)174 private native int nativeFinishPainting(int[] buffer, int width, int height); native_switch_theme()175 private native void native_switch_theme(); 176 177 static { 178 // Make sure the awt toolkit is loaded so we have access to native 179 // methods. Toolkit.getDefaultToolkit()180 Toolkit.getDefaultToolkit(); 181 182 // Initialize regionToWidgetTypeMap 183 regionToWidgetTypeMap = new HashMap<Region, Object>(50); regionToWidgetTypeMap.put(Region.ARROW_BUTTON, new WidgetType[] { WidgetType.SPINNER_ARROW_BUTTON, WidgetType.COMBO_BOX_ARROW_BUTTON, WidgetType.HSCROLL_BAR_BUTTON_LEFT, WidgetType.HSCROLL_BAR_BUTTON_RIGHT, WidgetType.VSCROLL_BAR_BUTTON_UP, WidgetType.VSCROLL_BAR_BUTTON_DOWN})184 regionToWidgetTypeMap.put(Region.ARROW_BUTTON, new WidgetType[] { 185 WidgetType.SPINNER_ARROW_BUTTON, 186 WidgetType.COMBO_BOX_ARROW_BUTTON, 187 WidgetType.HSCROLL_BAR_BUTTON_LEFT, 188 WidgetType.HSCROLL_BAR_BUTTON_RIGHT, 189 WidgetType.VSCROLL_BAR_BUTTON_UP, 190 WidgetType.VSCROLL_BAR_BUTTON_DOWN}); regionToWidgetTypeMap.put(Region.BUTTON, WidgetType.BUTTON)191 regionToWidgetTypeMap.put(Region.BUTTON, WidgetType.BUTTON); regionToWidgetTypeMap.put(Region.CHECK_BOX, WidgetType.CHECK_BOX)192 regionToWidgetTypeMap.put(Region.CHECK_BOX, WidgetType.CHECK_BOX); regionToWidgetTypeMap.put(Region.CHECK_BOX_MENU_ITEM, WidgetType.CHECK_BOX_MENU_ITEM)193 regionToWidgetTypeMap.put(Region.CHECK_BOX_MENU_ITEM, 194 WidgetType.CHECK_BOX_MENU_ITEM); regionToWidgetTypeMap.put(Region.COLOR_CHOOSER, WidgetType.COLOR_CHOOSER)195 regionToWidgetTypeMap.put(Region.COLOR_CHOOSER, WidgetType.COLOR_CHOOSER); regionToWidgetTypeMap.put(Region.FILE_CHOOSER, WidgetType.OPTION_PANE)196 regionToWidgetTypeMap.put(Region.FILE_CHOOSER, WidgetType.OPTION_PANE); regionToWidgetTypeMap.put(Region.COMBO_BOX, WidgetType.COMBO_BOX)197 regionToWidgetTypeMap.put(Region.COMBO_BOX, WidgetType.COMBO_BOX); regionToWidgetTypeMap.put(Region.DESKTOP_ICON, WidgetType.DESKTOP_ICON)198 regionToWidgetTypeMap.put(Region.DESKTOP_ICON, WidgetType.DESKTOP_ICON); regionToWidgetTypeMap.put(Region.DESKTOP_PANE, WidgetType.DESKTOP_PANE)199 regionToWidgetTypeMap.put(Region.DESKTOP_PANE, WidgetType.DESKTOP_PANE); regionToWidgetTypeMap.put(Region.EDITOR_PANE, WidgetType.EDITOR_PANE)200 regionToWidgetTypeMap.put(Region.EDITOR_PANE, WidgetType.EDITOR_PANE); regionToWidgetTypeMap.put(Region.FORMATTED_TEXT_FIELD, new WidgetType[] { WidgetType.FORMATTED_TEXT_FIELD, WidgetType.SPINNER_TEXT_FIELD})201 regionToWidgetTypeMap.put(Region.FORMATTED_TEXT_FIELD, new WidgetType[] { 202 WidgetType.FORMATTED_TEXT_FIELD, WidgetType.SPINNER_TEXT_FIELD}); regionToWidgetTypeMap.put(GTKRegion.HANDLE_BOX, WidgetType.HANDLE_BOX)203 regionToWidgetTypeMap.put(GTKRegion.HANDLE_BOX, WidgetType.HANDLE_BOX); regionToWidgetTypeMap.put(Region.INTERNAL_FRAME, WidgetType.INTERNAL_FRAME)204 regionToWidgetTypeMap.put(Region.INTERNAL_FRAME, 205 WidgetType.INTERNAL_FRAME); regionToWidgetTypeMap.put(Region.INTERNAL_FRAME_TITLE_PANE, WidgetType.INTERNAL_FRAME_TITLE_PANE)206 regionToWidgetTypeMap.put(Region.INTERNAL_FRAME_TITLE_PANE, 207 WidgetType.INTERNAL_FRAME_TITLE_PANE); regionToWidgetTypeMap.put(Region.LABEL, new WidgetType[] { WidgetType.LABEL, WidgetType.COMBO_BOX_TEXT_FIELD})208 regionToWidgetTypeMap.put(Region.LABEL, new WidgetType[] { 209 WidgetType.LABEL, WidgetType.COMBO_BOX_TEXT_FIELD}); regionToWidgetTypeMap.put(Region.LIST, WidgetType.LIST)210 regionToWidgetTypeMap.put(Region.LIST, WidgetType.LIST); regionToWidgetTypeMap.put(Region.MENU, WidgetType.MENU)211 regionToWidgetTypeMap.put(Region.MENU, WidgetType.MENU); regionToWidgetTypeMap.put(Region.MENU_BAR, WidgetType.MENU_BAR)212 regionToWidgetTypeMap.put(Region.MENU_BAR, WidgetType.MENU_BAR); regionToWidgetTypeMap.put(Region.MENU_ITEM, WidgetType.MENU_ITEM)213 regionToWidgetTypeMap.put(Region.MENU_ITEM, WidgetType.MENU_ITEM); regionToWidgetTypeMap.put(Region.MENU_ITEM_ACCELERATOR, WidgetType.MENU_ITEM_ACCELERATOR)214 regionToWidgetTypeMap.put(Region.MENU_ITEM_ACCELERATOR, 215 WidgetType.MENU_ITEM_ACCELERATOR); regionToWidgetTypeMap.put(Region.OPTION_PANE, WidgetType.OPTION_PANE)216 regionToWidgetTypeMap.put(Region.OPTION_PANE, WidgetType.OPTION_PANE); regionToWidgetTypeMap.put(Region.PANEL, WidgetType.PANEL)217 regionToWidgetTypeMap.put(Region.PANEL, WidgetType.PANEL); regionToWidgetTypeMap.put(Region.PASSWORD_FIELD, WidgetType.PASSWORD_FIELD)218 regionToWidgetTypeMap.put(Region.PASSWORD_FIELD, 219 WidgetType.PASSWORD_FIELD); regionToWidgetTypeMap.put(Region.POPUP_MENU, WidgetType.POPUP_MENU)220 regionToWidgetTypeMap.put(Region.POPUP_MENU, WidgetType.POPUP_MENU); regionToWidgetTypeMap.put(Region.POPUP_MENU_SEPARATOR, WidgetType.POPUP_MENU_SEPARATOR)221 regionToWidgetTypeMap.put(Region.POPUP_MENU_SEPARATOR, 222 WidgetType.POPUP_MENU_SEPARATOR); regionToWidgetTypeMap.put(Region.PROGRESS_BAR, new WidgetType[] { WidgetType.HPROGRESS_BAR, WidgetType.VPROGRESS_BAR})223 regionToWidgetTypeMap.put(Region.PROGRESS_BAR, new WidgetType[] { 224 WidgetType.HPROGRESS_BAR, WidgetType.VPROGRESS_BAR}); regionToWidgetTypeMap.put(Region.RADIO_BUTTON, WidgetType.RADIO_BUTTON)225 regionToWidgetTypeMap.put(Region.RADIO_BUTTON, WidgetType.RADIO_BUTTON); regionToWidgetTypeMap.put(Region.RADIO_BUTTON_MENU_ITEM, WidgetType.RADIO_BUTTON_MENU_ITEM)226 regionToWidgetTypeMap.put(Region.RADIO_BUTTON_MENU_ITEM, 227 WidgetType.RADIO_BUTTON_MENU_ITEM); regionToWidgetTypeMap.put(Region.ROOT_PANE, WidgetType.ROOT_PANE)228 regionToWidgetTypeMap.put(Region.ROOT_PANE, WidgetType.ROOT_PANE); regionToWidgetTypeMap.put(Region.SCROLL_BAR, new WidgetType[] { WidgetType.HSCROLL_BAR, WidgetType.VSCROLL_BAR})229 regionToWidgetTypeMap.put(Region.SCROLL_BAR, new WidgetType[] { 230 WidgetType.HSCROLL_BAR, WidgetType.VSCROLL_BAR}); regionToWidgetTypeMap.put(Region.SCROLL_BAR_THUMB, new WidgetType[] { WidgetType.HSCROLL_BAR_THUMB, WidgetType.VSCROLL_BAR_THUMB})231 regionToWidgetTypeMap.put(Region.SCROLL_BAR_THUMB, new WidgetType[] { 232 WidgetType.HSCROLL_BAR_THUMB, WidgetType.VSCROLL_BAR_THUMB}); regionToWidgetTypeMap.put(Region.SCROLL_BAR_TRACK, new WidgetType[] { WidgetType.HSCROLL_BAR_TRACK, WidgetType.VSCROLL_BAR_TRACK})233 regionToWidgetTypeMap.put(Region.SCROLL_BAR_TRACK, new WidgetType[] { 234 WidgetType.HSCROLL_BAR_TRACK, WidgetType.VSCROLL_BAR_TRACK}); regionToWidgetTypeMap.put(Region.SCROLL_PANE, WidgetType.SCROLL_PANE)235 regionToWidgetTypeMap.put(Region.SCROLL_PANE, WidgetType.SCROLL_PANE); regionToWidgetTypeMap.put(Region.SEPARATOR, new WidgetType[] { WidgetType.HSEPARATOR, WidgetType.VSEPARATOR})236 regionToWidgetTypeMap.put(Region.SEPARATOR, new WidgetType[] { 237 WidgetType.HSEPARATOR, WidgetType.VSEPARATOR}); regionToWidgetTypeMap.put(Region.SLIDER, new WidgetType[] { WidgetType.HSLIDER, WidgetType.VSLIDER})238 regionToWidgetTypeMap.put(Region.SLIDER, new WidgetType[] { 239 WidgetType.HSLIDER, WidgetType.VSLIDER}); regionToWidgetTypeMap.put(Region.SLIDER_THUMB, new WidgetType[] { WidgetType.HSLIDER_THUMB, WidgetType.VSLIDER_THUMB})240 regionToWidgetTypeMap.put(Region.SLIDER_THUMB, new WidgetType[] { 241 WidgetType.HSLIDER_THUMB, WidgetType.VSLIDER_THUMB}); regionToWidgetTypeMap.put(Region.SLIDER_TRACK, new WidgetType[] { WidgetType.HSLIDER_TRACK, WidgetType.VSLIDER_TRACK})242 regionToWidgetTypeMap.put(Region.SLIDER_TRACK, new WidgetType[] { 243 WidgetType.HSLIDER_TRACK, WidgetType.VSLIDER_TRACK}); regionToWidgetTypeMap.put(Region.SPINNER, WidgetType.SPINNER)244 regionToWidgetTypeMap.put(Region.SPINNER, WidgetType.SPINNER); regionToWidgetTypeMap.put(Region.SPLIT_PANE, WidgetType.SPLIT_PANE)245 regionToWidgetTypeMap.put(Region.SPLIT_PANE, WidgetType.SPLIT_PANE); regionToWidgetTypeMap.put(Region.SPLIT_PANE_DIVIDER, new WidgetType[] { WidgetType.HSPLIT_PANE_DIVIDER, WidgetType.VSPLIT_PANE_DIVIDER})246 regionToWidgetTypeMap.put(Region.SPLIT_PANE_DIVIDER, new WidgetType[] { 247 WidgetType.HSPLIT_PANE_DIVIDER, WidgetType.VSPLIT_PANE_DIVIDER}); regionToWidgetTypeMap.put(Region.TABBED_PANE, WidgetType.TABBED_PANE)248 regionToWidgetTypeMap.put(Region.TABBED_PANE, WidgetType.TABBED_PANE); regionToWidgetTypeMap.put(Region.TABBED_PANE_CONTENT, WidgetType.TABBED_PANE_CONTENT)249 regionToWidgetTypeMap.put(Region.TABBED_PANE_CONTENT, 250 WidgetType.TABBED_PANE_CONTENT); regionToWidgetTypeMap.put(Region.TABBED_PANE_TAB, WidgetType.TABBED_PANE_TAB)251 regionToWidgetTypeMap.put(Region.TABBED_PANE_TAB, 252 WidgetType.TABBED_PANE_TAB); regionToWidgetTypeMap.put(Region.TABBED_PANE_TAB_AREA, WidgetType.TABBED_PANE_TAB_AREA)253 regionToWidgetTypeMap.put(Region.TABBED_PANE_TAB_AREA, 254 WidgetType.TABBED_PANE_TAB_AREA); regionToWidgetTypeMap.put(Region.TABLE, WidgetType.TABLE)255 regionToWidgetTypeMap.put(Region.TABLE, WidgetType.TABLE); regionToWidgetTypeMap.put(Region.TABLE_HEADER, WidgetType.TABLE_HEADER)256 regionToWidgetTypeMap.put(Region.TABLE_HEADER, WidgetType.TABLE_HEADER); regionToWidgetTypeMap.put(Region.TEXT_AREA, WidgetType.TEXT_AREA)257 regionToWidgetTypeMap.put(Region.TEXT_AREA, WidgetType.TEXT_AREA); regionToWidgetTypeMap.put(Region.TEXT_FIELD, new WidgetType[] { WidgetType.TEXT_FIELD, WidgetType.COMBO_BOX_TEXT_FIELD})258 regionToWidgetTypeMap.put(Region.TEXT_FIELD, new WidgetType[] { 259 WidgetType.TEXT_FIELD, WidgetType.COMBO_BOX_TEXT_FIELD}); regionToWidgetTypeMap.put(Region.TEXT_PANE, WidgetType.TEXT_PANE)260 regionToWidgetTypeMap.put(Region.TEXT_PANE, WidgetType.TEXT_PANE); regionToWidgetTypeMap.put(CustomRegion.TITLED_BORDER, WidgetType.TITLED_BORDER)261 regionToWidgetTypeMap.put(CustomRegion.TITLED_BORDER, WidgetType.TITLED_BORDER); regionToWidgetTypeMap.put(Region.TOGGLE_BUTTON, WidgetType.TOGGLE_BUTTON)262 regionToWidgetTypeMap.put(Region.TOGGLE_BUTTON, WidgetType.TOGGLE_BUTTON); regionToWidgetTypeMap.put(Region.TOOL_BAR, WidgetType.TOOL_BAR)263 regionToWidgetTypeMap.put(Region.TOOL_BAR, WidgetType.TOOL_BAR); regionToWidgetTypeMap.put(Region.TOOL_BAR_CONTENT, WidgetType.TOOL_BAR)264 regionToWidgetTypeMap.put(Region.TOOL_BAR_CONTENT, WidgetType.TOOL_BAR); regionToWidgetTypeMap.put(Region.TOOL_BAR_DRAG_WINDOW, WidgetType.TOOL_BAR_DRAG_WINDOW)265 regionToWidgetTypeMap.put(Region.TOOL_BAR_DRAG_WINDOW, 266 WidgetType.TOOL_BAR_DRAG_WINDOW); regionToWidgetTypeMap.put(Region.TOOL_BAR_SEPARATOR, WidgetType.TOOL_BAR_SEPARATOR)267 regionToWidgetTypeMap.put(Region.TOOL_BAR_SEPARATOR, 268 WidgetType.TOOL_BAR_SEPARATOR); regionToWidgetTypeMap.put(Region.TOOL_TIP, WidgetType.TOOL_TIP)269 regionToWidgetTypeMap.put(Region.TOOL_TIP, WidgetType.TOOL_TIP); regionToWidgetTypeMap.put(Region.TREE, WidgetType.TREE)270 regionToWidgetTypeMap.put(Region.TREE, WidgetType.TREE); regionToWidgetTypeMap.put(Region.TREE_CELL, WidgetType.TREE_CELL)271 regionToWidgetTypeMap.put(Region.TREE_CELL, WidgetType.TREE_CELL); regionToWidgetTypeMap.put(Region.VIEWPORT, WidgetType.VIEWPORT)272 regionToWidgetTypeMap.put(Region.VIEWPORT, WidgetType.VIEWPORT); 273 } 274 275 /** Translate Region and JComponent into WidgetType ordinals */ getWidgetType(JComponent c, Region id)276 static WidgetType getWidgetType(JComponent c, Region id) { 277 Object value = regionToWidgetTypeMap.get(id); 278 279 if (value instanceof WidgetType) { 280 return (WidgetType)value; 281 } 282 283 WidgetType[] widgets = (WidgetType[])value; 284 if (c == null ) { 285 return widgets[0]; 286 } 287 288 if (c instanceof JScrollBar) { 289 return (((JScrollBar)c).getOrientation() == JScrollBar.HORIZONTAL) ? 290 widgets[0] : widgets[1]; 291 } else if (c instanceof JSeparator) { 292 JSeparator separator = (JSeparator)c; 293 294 /* We should return correrct WidgetType if the seperator is inserted 295 * in Menu/PopupMenu/ToolBar. BugID: 6465603 296 */ 297 if (separator.getParent() instanceof JPopupMenu) { 298 return WidgetType.POPUP_MENU_SEPARATOR; 299 } else if (separator.getParent() instanceof JToolBar) { 300 return WidgetType.TOOL_BAR_SEPARATOR; 301 } 302 303 return (separator.getOrientation() == JSeparator.HORIZONTAL) ? 304 widgets[0] : widgets[1]; 305 } else if (c instanceof JSlider) { 306 return (((JSlider)c).getOrientation() == JSlider.HORIZONTAL) ? 307 widgets[0] : widgets[1]; 308 } else if (c instanceof JProgressBar) { 309 return (((JProgressBar)c).getOrientation() == JProgressBar.HORIZONTAL) ? 310 widgets[0] : widgets[1]; 311 } else if (c instanceof JSplitPane) { 312 return (((JSplitPane)c).getOrientation() == JSplitPane.HORIZONTAL_SPLIT) ? 313 widgets[1] : widgets[0]; 314 } else if (id == Region.LABEL) { 315 /* 316 * For all ListCellRenderers we will use COMBO_BOX_TEXT_FIELD widget 317 * type because we can get correct insets. List items however won't be 318 * drawn as a text entry (see GTKPainter.paintLabelBackground). 319 */ 320 if (c instanceof ListCellRenderer) { 321 return widgets[1]; 322 } else { 323 return widgets[0]; 324 } 325 } else if (id == Region.TEXT_FIELD) { 326 String name = c.getName(); 327 if (name != null && name.startsWith("ComboBox")) { 328 return widgets[1]; 329 } else { 330 return widgets[0]; 331 } 332 } else if (id == Region.FORMATTED_TEXT_FIELD) { 333 String name = c.getName(); 334 if (name != null && name.startsWith("Spinner")) { 335 return widgets[1]; 336 } else { 337 return widgets[0]; 338 } 339 } else if (id == Region.ARROW_BUTTON) { 340 if (c.getParent() instanceof JScrollBar) { 341 Integer prop = (Integer) 342 c.getClientProperty("__arrow_direction__"); 343 int dir = (prop != null) ? 344 prop.intValue() : SwingConstants.WEST; 345 switch (dir) { 346 case SwingConstants.WEST: 347 return WidgetType.HSCROLL_BAR_BUTTON_LEFT; 348 case SwingConstants.EAST: 349 return WidgetType.HSCROLL_BAR_BUTTON_RIGHT; 350 case SwingConstants.NORTH: 351 return WidgetType.VSCROLL_BAR_BUTTON_UP; 352 case SwingConstants.SOUTH: 353 return WidgetType.VSCROLL_BAR_BUTTON_DOWN; 354 default: 355 return null; 356 } 357 } else if (c.getParent() instanceof JComboBox) { 358 return WidgetType.COMBO_BOX_ARROW_BUTTON; 359 } else { 360 return WidgetType.SPINNER_ARROW_BUTTON; 361 } 362 } 363 364 return null; 365 } 366 getTextDirection(SynthContext context)367 private static int getTextDirection(SynthContext context) { 368 TextDirection dir = TextDirection.NONE; 369 JComponent comp = context.getComponent(); 370 if (comp != null) { 371 ComponentOrientation co = comp.getComponentOrientation(); 372 if (co != null) { 373 dir = co.isLeftToRight() ? 374 TextDirection.LTR : TextDirection.RTL; 375 } 376 } 377 return dir.ordinal(); 378 } 379 paintArrow(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, ArrowType direction, String detail, int x, int y, int w, int h)380 public void paintArrow(Graphics g, SynthContext context, 381 Region id, int state, ShadowType shadowType, ArrowType direction, 382 String detail, int x, int y, int w, int h) { 383 384 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 385 int widget = getWidgetType(context.getComponent(), id).ordinal(); 386 native_paint_arrow(widget, state, shadowType.ordinal(), 387 detail, x - x0, y - y0, w, h, direction.ordinal()); 388 } 389 paintBox(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, String detail, int x, int y, int w, int h)390 public void paintBox(Graphics g, SynthContext context, 391 Region id, int state, ShadowType shadowType, 392 String detail, int x, int y, int w, int h) { 393 394 int gtkState = 395 GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 396 int synthState = context.getComponentState(); 397 int dir = getTextDirection(context); 398 int widget = getWidgetType(context.getComponent(), id).ordinal(); 399 native_paint_box(widget, gtkState, shadowType.ordinal(), 400 detail, x - x0, y - y0, w, h, synthState, dir); 401 } 402 paintBoxGap(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, String detail, int x, int y, int w, int h, PositionType boxGapType, int tabBegin, int size)403 public void paintBoxGap(Graphics g, SynthContext context, 404 Region id, int state, ShadowType shadowType, 405 String detail, int x, int y, int w, int h, 406 PositionType boxGapType, int tabBegin, int size) { 407 408 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 409 int widget = getWidgetType(context.getComponent(), id).ordinal(); 410 native_paint_box_gap(widget, state, shadowType.ordinal(), detail, 411 x - x0, y - y0, w, h, boxGapType.ordinal(), tabBegin, size); 412 } 413 paintCheck(Graphics g, SynthContext context, Region id, String detail, int x, int y, int w, int h)414 public void paintCheck(Graphics g, SynthContext context, 415 Region id, String detail, int x, int y, int w, int h) { 416 417 int synthState = context.getComponentState(); 418 int widget = getWidgetType(context.getComponent(), id).ordinal(); 419 native_paint_check(widget, synthState, detail, x - x0, y - y0, w, h); 420 } 421 paintExpander(Graphics g, SynthContext context, Region id, int state, ExpanderStyle expanderStyle, String detail, int x, int y, int w, int h)422 public void paintExpander(Graphics g, SynthContext context, 423 Region id, int state, ExpanderStyle expanderStyle, String detail, 424 int x, int y, int w, int h) { 425 426 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 427 int widget = getWidgetType(context.getComponent(), id).ordinal(); 428 native_paint_expander(widget, state, detail, x - x0, y - y0, w, h, 429 expanderStyle.ordinal()); 430 } 431 paintExtension(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, String detail, int x, int y, int w, int h, PositionType placement, int tabIndex)432 public void paintExtension(Graphics g, SynthContext context, 433 Region id, int state, ShadowType shadowType, String detail, 434 int x, int y, int w, int h, PositionType placement, int tabIndex) { 435 436 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 437 int widget = getWidgetType(context.getComponent(), id).ordinal(); 438 native_paint_extension(widget, state, shadowType.ordinal(), detail, 439 x - x0, y - y0, w, h, placement.ordinal()); 440 } 441 paintFlatBox(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, String detail, int x, int y, int w, int h, ColorType colorType)442 public void paintFlatBox(Graphics g, SynthContext context, 443 Region id, int state, ShadowType shadowType, String detail, 444 int x, int y, int w, int h, ColorType colorType) { 445 446 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 447 int widget = getWidgetType(context.getComponent(), id).ordinal(); 448 native_paint_flat_box(widget, state, shadowType.ordinal(), detail, 449 x - x0, y - y0, w, h, 450 context.getComponent().hasFocus()); 451 } 452 paintFocus(Graphics g, SynthContext context, Region id, int state, String detail, int x, int y, int w, int h)453 public void paintFocus(Graphics g, SynthContext context, 454 Region id, int state, String detail, int x, int y, int w, int h) { 455 456 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 457 int widget = getWidgetType(context.getComponent(), id).ordinal(); 458 native_paint_focus(widget, state, detail, x - x0, y - y0, w, h); 459 } 460 paintHandle(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, String detail, int x, int y, int w, int h, Orientation orientation)461 public void paintHandle(Graphics g, SynthContext context, 462 Region id, int state, ShadowType shadowType, String detail, 463 int x, int y, int w, int h, Orientation orientation) { 464 465 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 466 int widget = getWidgetType(context.getComponent(), id).ordinal(); 467 native_paint_handle(widget, state, shadowType.ordinal(), detail, 468 x - x0, y - y0, w, h, orientation.ordinal()); 469 } 470 paintHline(Graphics g, SynthContext context, Region id, int state, String detail, int x, int y, int w, int h)471 public void paintHline(Graphics g, SynthContext context, 472 Region id, int state, String detail, int x, int y, int w, int h) { 473 474 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 475 int widget = getWidgetType(context.getComponent(), id).ordinal(); 476 native_paint_hline(widget, state, detail, x - x0, y - y0, w, h); 477 } 478 paintOption(Graphics g, SynthContext context, Region id, String detail, int x, int y, int w, int h)479 public void paintOption(Graphics g, SynthContext context, 480 Region id, String detail, int x, int y, int w, int h) { 481 482 int synthState = context.getComponentState(); 483 int widget = getWidgetType(context.getComponent(), id).ordinal(); 484 native_paint_option(widget, synthState, detail, x - x0, y - y0, w, h); 485 } 486 paintShadow(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, String detail, int x, int y, int w, int h)487 public void paintShadow(Graphics g, SynthContext context, 488 Region id, int state, ShadowType shadowType, String detail, 489 int x, int y, int w, int h) { 490 491 int gtkState = 492 GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 493 int synthState = context.getComponentState(); 494 Container parent = context.getComponent().getParent(); 495 if(GTKLookAndFeel.is3()) { 496 if (parent != null && parent.getParent() instanceof JComboBox) { 497 if (parent.getParent().hasFocus()) { 498 synthState |= SynthConstants.FOCUSED; 499 } 500 } 501 } 502 int dir = getTextDirection(context); 503 int widget = getWidgetType(context.getComponent(), id).ordinal(); 504 native_paint_shadow(widget, gtkState, shadowType.ordinal(), detail, 505 x - x0, y - y0, w, h, synthState, dir); 506 } 507 paintSlider(Graphics g, SynthContext context, Region id, int state, ShadowType shadowType, String detail, int x, int y, int w, int h, Orientation orientation, boolean hasFocus)508 public void paintSlider(Graphics g, SynthContext context, 509 Region id, int state, ShadowType shadowType, String detail, int x, 510 int y, int w, int h, Orientation orientation, boolean hasFocus) { 511 512 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 513 int widget = getWidgetType(context.getComponent(), id).ordinal(); 514 native_paint_slider(widget, state, shadowType.ordinal(), detail, 515 x - x0, y - y0, w, h, orientation.ordinal(), hasFocus); 516 } 517 paintVline(Graphics g, SynthContext context, Region id, int state, String detail, int x, int y, int w, int h)518 public void paintVline(Graphics g, SynthContext context, 519 Region id, int state, String detail, int x, int y, int w, int h) { 520 521 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 522 int widget = getWidgetType(context.getComponent(), id).ordinal(); 523 native_paint_vline(widget, state, detail, x - x0, y - y0, w, h); 524 } 525 paintBackground(Graphics g, SynthContext context, Region id, int state, Color color, int x, int y, int w, int h)526 public void paintBackground(Graphics g, SynthContext context, 527 Region id, int state, Color color, int x, int y, int w, int h) { 528 529 state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal(); 530 int widget = getWidgetType(context.getComponent(), id).ordinal(); 531 native_paint_background(widget, state, x - x0, y - y0, w, h); 532 } 533 534 private final static ColorModel[] COLOR_MODELS = { 535 // Transparency.OPAQUE 536 new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000), 537 // Transparency.BITMASK 538 new DirectColorModel(25, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x01000000), 539 // Transparency.TRANSLUCENT 540 ColorModel.getRGBdefault(), 541 }; 542 543 private final static int[][] BAND_OFFSETS = { 544 { 0x00ff0000, 0x0000ff00, 0x000000ff }, // OPAQUE 545 { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x01000000 }, // BITMASK 546 { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 } // TRANSLUCENT 547 }; 548 549 550 /** 551 * Paint a cached image identified by its size and a set of additional 552 * arguments, if there's one. 553 * 554 * @return true if a cached image has been painted, false otherwise 555 */ paintCachedImage(Graphics g, int x, int y, int w, int h, Object... args)556 public boolean paintCachedImage(Graphics g, 557 int x, int y, int w, int h, Object... args) { 558 if (w <= 0 || h <= 0) { 559 return true; 560 } 561 562 // look for cached image 563 Image img = cache.getImage(getClass(), null, w, h, args); 564 if (img != null) { 565 g.drawImage(img, x, y, null); 566 return true; 567 } 568 return false; 569 } 570 571 /* 572 * Allocate a native offscreen buffer of the specified size. 573 */ startPainting(Graphics g, int x, int y, int w, int h, Object... args)574 public void startPainting(Graphics g, 575 int x, int y, int w, int h, Object... args) { 576 nativeStartPainting(w, h); 577 x0 = x; 578 y0 = y; 579 w0 = w; 580 h0 = h; 581 graphics = g; 582 cacheArgs = args; 583 } 584 585 /** 586 * Convenience method that delegates to finishPainting() with 587 * caching enabled. 588 */ finishPainting()589 public BufferedImage finishPainting() { 590 return finishPainting(true); 591 } 592 593 /** 594 * Called to indicate that painting is finished. We create a new 595 * BufferedImage from the offscreen buffer, (optionally) cache it, 596 * and paint it. 597 */ finishPainting(boolean useCache)598 public BufferedImage finishPainting(boolean useCache) { 599 DataBufferInt dataBuffer = new DataBufferInt(w0 * h0); 600 // Note that stealData() requires a markDirty() afterwards 601 // since we modify the data in it. 602 int transparency = 603 nativeFinishPainting(SunWritableRaster.stealData(dataBuffer, 0), 604 w0, h0); 605 SunWritableRaster.markDirty(dataBuffer); 606 607 int[] bands = BAND_OFFSETS[transparency - 1]; 608 WritableRaster raster = Raster.createPackedRaster( 609 dataBuffer, w0, h0, w0, bands, null); 610 611 ColorModel cm = COLOR_MODELS[transparency - 1]; 612 BufferedImage img = new BufferedImage(cm, raster, false, null); 613 if (useCache) { 614 cache.setImage(getClass(), null, w0, h0, cacheArgs, img); 615 } 616 graphics.drawImage(img, x0, y0, null); 617 return img; 618 } 619 620 /** 621 * Notify native layer of theme change, and flush cache 622 */ themeChanged()623 public void themeChanged() { 624 synchronized(sun.awt.UNIXToolkit.GTK_LOCK) { 625 native_switch_theme(); 626 } 627 cache.flush(); 628 } 629 630 /* GtkSettings enum mirrors that in gtk2_interface.h */ getSetting(Settings property)631 public Object getSetting(Settings property) { 632 synchronized(sun.awt.UNIXToolkit.GTK_LOCK) { 633 return native_get_gtk_setting(property.ordinal()); 634 } 635 } 636 637 /** 638 * Sets up the GtkAdjustment values for the native GtkRange widget 639 * associated with the given region (e.g. SLIDER, SCROLL_BAR). 640 */ setRangeValue(SynthContext context, Region id, double value, double min, double max, double visible)641 void setRangeValue(SynthContext context, Region id, 642 double value, double min, double max, double visible) { 643 int widget = getWidgetType(context.getComponent(), id).ordinal(); 644 nativeSetRangeValue(widget, value, min, max, visible); 645 } 646 } 647