| 182 | private Object textLineCache = null; |
| 183 | private Object getTextLine() { |
| 184 | |
| 185 | if (this.textLineCache == null) { |
| 186 | TextLayout awtLayout = toAwtLayout(); |
| 187 | Field textLineField; |
| 188 | try { |
| 189 | textLineField = awtLayout.getClass().getDeclaredField("textLine"); |
| 190 | textLineField.setAccessible(true); |
| 191 | this.textLineCache = textLineField.get(awtLayout); |
| 192 | } catch (SecurityException e) { |
| 193 | throw new RuntimeException(e); |
| 194 | } catch (NoSuchFieldException e) { |
| 195 | throw new RuntimeException(e); |
| 196 | } catch (IllegalArgumentException e) { |
| 197 | throw new RuntimeException(e); |
| 198 | } catch (IllegalAccessException e) { |
| 199 | throw new RuntimeException(e); |
| 200 | } |
| 201 | } |
| 202 | |
| 203 | return this.textLineCache; |
| 204 | } |
| 205 | |
| 206 | private Object[] componentsCache = null; |
| 207 | private Object[] getComponents() { |
| 208 | |
| 209 | if (this.componentsCache == null) { |
| 210 | try { |
| 211 | Object textLine = getTextLine(); |
| 212 | Field fComponentsField = textLine.getClass().getDeclaredField("fComponents"); |
| 213 | fComponentsField.setAccessible(true); |
| 214 | this.componentsCache = (Object[]) fComponentsField.get(textLine); |
| 215 | } catch (SecurityException e) { |
| 216 | throw new RuntimeException(e); |
| 217 | } catch (NoSuchFieldException e) { |
| 218 | throw new RuntimeException(e); |
| 219 | } catch (IllegalArgumentException e) { |
| 220 | throw new RuntimeException(e); |
| 221 | } catch (IllegalAccessException e) { |
| 222 | throw new RuntimeException(e); |
| 223 | } |
| 224 | } |
| 225 | return this.componentsCache; |
| 226 | } |
| 227 | |
| 228 | private int[] componentsVisualOrderCache = null; |
| 229 | private int[] getComponentsVisualOrder() { |
| 230 | |
| 231 | if (this.componentsVisualOrderCache == null) { |
| 232 | try { |
| 233 | Object textLine = getTextLine(); |
| 234 | Field fComponentVisualOrderField = textLine.getClass().getDeclaredField("fComponentVisualOrder"); |
| 235 | fComponentVisualOrderField.setAccessible(true); |
| 236 | this.componentsVisualOrderCache = (int[])fComponentVisualOrderField.get(textLine); |
| 237 | } catch (IllegalAccessException e) { |
| 238 | throw new RuntimeException(e); |
| 239 | } catch (NoSuchFieldException e) { |
| 240 | throw new RuntimeException(e); |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | return this.componentsVisualOrderCache; |
| 245 | } |
| 246 | |
| 247 | private float[] locsCache = null; |
| 248 | private float[] getLocs() { |
| 249 | if (this.locsCache == null) { |
| 250 | try { |
| 251 | Object textLine = getTextLine(); |
| 252 | |
| 253 | Field locsField = textLine.getClass().getDeclaredField("locs"); |
| 254 | locsField.setAccessible(true); |
| 255 | this.locsCache = (float[])locsField.get(textLine); |
| 256 | } catch (IllegalAccessException e) { |
| 257 | throw new RuntimeException(e); |
| 258 | } catch (NoSuchFieldException e) { |
| 259 | throw new RuntimeException(e); |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | return this.locsCache; |
| 264 | } |
| 265 | |
| 266 | private void drawLayout(Graphics2D g2, float x, float y) { |
| 267 | |
| 268 | |
| 269 | try { |
| 270 | Object[] components = getComponents(); |
| 271 | int length = components.length; |
| 272 | |
| 273 | int[] componentVisualOrder = getComponentsVisualOrder(); |
| 274 | float[] locs = getLocs(); |
| 275 | |
| 276 | for (int i = 0, n = 0; i < length; i++, n += 2) { |
| 277 | int vi = componentVisualOrder==null? i : (Integer)componentVisualOrder[i]; |
| 278 | |
| 279 | Method getOutlineMethod |
| 280 | = components[vi].getClass().getDeclaredMethod("getOutline", float.class, float.class); |
| 281 | getOutlineMethod.setAccessible(true); |
| 282 | |
| 283 | Object outlineArgs[] = new Object[2]; |
| 284 | outlineArgs[0] = new Float(locs[n] + x); |
| 285 | outlineArgs[1] = new Float(locs[n+1] + y); |
| 286 | |
| 287 | Shape outlineShape = (Shape)getOutlineMethod.invoke(components[vi], outlineArgs); |
| 288 | |
| 289 | Field decoratorField = components[vi].getClass().getDeclaredField("decorator"); |
| 290 | decoratorField.setAccessible(true); |
| 291 | Object decorator = decoratorField.get(components[vi]); |
| 292 | |
| 293 | Field fgPaintField = decorator.getClass().getDeclaredField("fgPaint"); |
| 294 | fgPaintField.setAccessible(true); |
| 295 | Color fgColor = (Color)fgPaintField.get(decorator); |
| 296 | |
| 297 | Field bgPaintField = decorator.getClass().getDeclaredField("bgPaint"); |
| 298 | bgPaintField.setAccessible(true); |
| 299 | |
| 300 | Color bgColor = (Color)bgPaintField.get(decorator); |
| 301 | |
| 302 | if (bgColor.getAlpha() != 0) { |
| 303 | |
| 304 | Method getLogicalBoundsMethod = |
| 305 | components[vi].getClass().getDeclaredMethod("getLogicalBounds", float.class, float.class); |
| 306 | getLogicalBoundsMethod.setAccessible(true); |
| 307 | Rectangle2D background = (Rectangle2D) getLogicalBoundsMethod.invoke(components[vi], outlineArgs); |
| 308 | |
| 309 | background = new Rectangle2D.Float(x + (float)background.getX(), |
| 310 | y + (float)background.getY(), |
| 311 | (float)background.getWidth(), |
| 312 | (float)background.getHeight()); |
| 313 | |
| 314 | g2.setColor(bgColor); |
| 315 | g2.fill(background); |
| 316 | } |
| 317 | |
| 318 | g2.setColor(fgColor); |
| 319 | g2.fill(outlineShape); |
| 320 | } |
| 321 | } catch (NoSuchFieldException e) { |
| 322 | throw new RuntimeException(e); |
| 323 | } catch (IllegalAccessException e) { |
| 324 | throw new RuntimeException(e); |
| 325 | } catch (NoSuchMethodException e) { |
| 326 | throw new RuntimeException(e); |
| 327 | } catch (InvocationTargetException e) { |
| 328 | throw new RuntimeException(e); |
| 329 | } |
| 330 | } |
| 331 | |