OSDN Git Service

dmg作成バージョンの取得方法の修正
[charactermanaj/CharacterManaJ.git] / src / charactermanaj / ui / Wallpaper.java
1 package charactermanaj.ui;\r
2 \r
3 import static java.lang.Math.ceil;\r
4 \r
5 import java.awt.AlphaComposite;\r
6 import java.awt.Color;\r
7 import java.awt.Composite;\r
8 import java.awt.Graphics2D;\r
9 import java.awt.GraphicsConfiguration;\r
10 import java.awt.Image;\r
11 import java.awt.Rectangle;\r
12 import java.awt.Transparency;\r
13 import java.awt.image.BufferedImage;\r
14 import java.awt.image.VolatileImage;\r
15 import java.beans.PropertyChangeListener;\r
16 import java.beans.PropertyChangeSupport;\r
17 import java.util.logging.Level;\r
18 import java.util.logging.Logger;\r
19 \r
20 import charactermanaj.model.AppConfig;\r
21 \r
22 /**\r
23  * 壁紙\r
24  * @author seraphy\r
25  */\r
26 public class Wallpaper {\r
27         \r
28         /**\r
29          * ロガー\r
30          */\r
31         private static final Logger logger = Logger.getLogger(Wallpaper.class.getName());\r
32 \r
33         /**\r
34          * 壁紙の推奨されるブロックサイズ(幅).<br>\r
35          * このサイズに満たない壁紙用画像は、このサイズに近い値まで敷き詰めて保持しておく.<br>\r
36          */\r
37         private static final int wallpaperPreferredWidth = 128;\r
38 \r
39         /**\r
40          * 壁紙の推奨されるブロックサイズ(高さ).<br>\r
41          * このサイズに満たない壁紙用画像は、このサイズに近い値まで敷き詰めて保持しておく.<br>\r
42          */\r
43         private static final int wallpaperPreferredHeight = 128;\r
44         \r
45         /**\r
46          * プロパティ変更イベントのキー名\r
47          */\r
48         public static final String KEY_WALLPAPER_IMAGE = "wallpaperImage";\r
49         \r
50         /**\r
51          * プロパティ変更通知サポート.\r
52          */\r
53         private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);\r
54         \r
55         /**\r
56          * 背景色.<br>\r
57          */\r
58         private Color backgroundColor = Color.WHITE;\r
59         \r
60         /**\r
61          * 壁紙画像.<br>\r
62          */\r
63         private BufferedImage wallpaperImg;\r
64         \r
65         /**\r
66          * 壁紙画像のアルファ値.<br>\r
67          */\r
68         private float wallpaperAlpha = 1.f;\r
69         \r
70         /**\r
71          * 壁紙用オフスクリーンサーフェイス.<br>\r
72          * なければnull.<br>\r
73          */\r
74         private VolatileImage wallpaperVolatileImg;\r
75         \r
76         /**\r
77          * 壁紙用オフスクリーンを生成したときに使用した背景色.<br>\r
78          * なければnull\r
79          */\r
80         private Color wallpaperVolatileBgColor;\r
81         \r
82         \r
83         /**\r
84          * 壁紙が表示されない状態で壁紙イメージを構築する.<br>\r
85          */\r
86         public Wallpaper() {\r
87                 this(null);\r
88         }\r
89 \r
90         /**\r
91          * 壁紙の元画像を指定して壁紙イメージを構築する.<br>\r
92          * nullを指定した場合は壁紙は表示されない.<br>\r
93          * @param wallpaperImg 壁紙イメージ、もしくはnull\r
94          */\r
95         public Wallpaper(BufferedImage wallpaperImg) {\r
96                 this.wallpaperImg = makeExpandedWallpaper(makeExpandedWallpaper(wallpaperImg));\r
97         }\r
98 \r
99         /**\r
100          * 壁紙画像を設定する.<br>\r
101          * nullの場合は解除される.<br>\r
102          * 壁紙が小さい場合は推奨されるブロックサイズまで敷き詰めなおした状態で\r
103          * 保持する.(描画不可軽減のため.)\r
104          * したがって、{@link #getWallpaperImage()}を呼び出したときには\r
105          * 拡張されたサイズとなっている.<br>\r
106          * @param wallpaperImg\r
107          */\r
108         public void setWallpaperImage(BufferedImage wallpaperImg) {\r
109                 // 現在のオフスクリーンを破棄する.\r
110                 disposeOffscreen();\r
111 \r
112                 // 新しいイメージ\r
113                 BufferedImage wallpaperImgOld = makeExpandedWallpaper(this.wallpaperImg);\r
114                 this.wallpaperImg = makeExpandedWallpaper(wallpaperImg);\r
115                 propertyChangeSupport.firePropertyChange("wallpaperImage", wallpaperImgOld, this.wallpaperImg);\r
116         }\r
117 \r
118         /**\r
119          * 壁紙画像を取得する.<br>\r
120          * 壁紙画像はブロックサイズまで拡張されたものとなっている.<br>\r
121          * @return 壁紙画像、なければnull\r
122          */\r
123         public BufferedImage getWallpaperImage() {\r
124                 return wallpaperImg;\r
125         }\r
126         \r
127         public float getWallpaperAlpha() {\r
128                 return wallpaperAlpha;\r
129         }\r
130         \r
131         /**\r
132          * 壁紙画像を描画する場合のアルファ値を設定する.<br>\r
133          * 負の値は0に、1以上は1に制限される.<br>\r
134          * @param wallpaperAlpha アルファ値(0から1の範囲)\r
135          */\r
136         public void setWallpaperAlpha(float wallpaperAlpha) {\r
137                 // 現在のオフスクリーンを破棄する.\r
138                 disposeOffscreen();\r
139 \r
140                 // 範囲無いに制限する.\r
141                 if (wallpaperAlpha < 0) {\r
142                         wallpaperAlpha = 0;\r
143                 } else if (wallpaperAlpha > 1.f) {\r
144                         wallpaperAlpha = 1.f;\r
145                 }\r
146 \r
147                 // アルファ値を設定する.\r
148                 float oldalpha = this.wallpaperAlpha;\r
149                 if (oldalpha != wallpaperAlpha) {\r
150                         this.wallpaperAlpha = wallpaperAlpha;\r
151                         propertyChangeSupport.firePropertyChange("wallpaperAlpha", oldalpha, wallpaperAlpha);\r
152                 }\r
153         }\r
154         \r
155         public Color getBackgroundColor() {\r
156                 return backgroundColor;\r
157         }\r
158         \r
159         public void setBackgroundColor(Color backgroundColor) {\r
160                 // 現在のオフスクリーンを破棄する.\r
161                 disposeOffscreen();\r
162 \r
163                 // 色が省略された場合の補正.\r
164                 if (backgroundColor == null) {\r
165                         backgroundColor = Color.WHITE;\r
166                 }\r
167                 \r
168                 // 背景色を設定する.\r
169                 Color colorOld = this.backgroundColor;\r
170                 if ( !colorOld.equals(backgroundColor)) {\r
171                         this.backgroundColor = backgroundColor;\r
172                         propertyChangeSupport.firePropertyChange("backgroundColor", colorOld, backgroundColor);\r
173                 }\r
174         }\r
175 \r
176         /**\r
177          * 壁紙を左上(0,0)を原点に指定した幅・高さでタイル状に敷き詰めて描画します.<br>\r
178          * 壁紙が設定されていなければ何もしません.<br>\r
179          * アプリケーション設定でオフスクリーンの使用が有効である場合、グラフィクスコンテキストに\r
180          * あわせてオフスクリーンイメージをあらかじめキャッシュとして作成して転送する.<br>\r
181          * オフスクリーンは初回描画時に構築され、以降、必要に応じて再作成される.<br>\r
182          * オフスクリーンを即座に破棄する場合には{@link #disposeOffscreen()}を呼び出す.<br>\r
183          * @param g 描画先\r
184          * @param bgColor 背景色\r
185          * @param w 幅 (画面幅)\r
186          * @param h 高さ (画面高)\r
187          */\r
188         public void drawWallpaper(Graphics2D g, int w, int h) {\r
189                 drawWallpaper(g, w, h, false);\r
190         }\r
191         \r
192         /**\r
193          * 壁紙を左上(0,0)を原点に指定した幅・高さでタイル状に敷き詰めて描画します.<br>\r
194          * 壁紙が設定されていなければ何もしません.<br>\r
195          * アプリケーション設定でオフスクリーンの使用が有効である場合、グラフィクスコンテキストに\r
196          * あわせてオフスクリーンイメージをあらかじめキャッシュとして作成して転送する.<br>\r
197          * ただし、引数でオフスクリーンを使用しないと指定した場合はオフスクリーンには一切関知せず、\r
198          * 通常の画像による背景描画を行う.<br>\r
199          * (この場合、オフスクリーンは作成されず、現在あるものを再作成も破棄もしない.)\r
200          * @param g 描画先\r
201          * @param bgColor 背景色\r
202          * @param w 幅 (画面幅)\r
203          * @param h 高さ (画面高)\r
204          * @param noUseOffscreen オフスクリーンを使用しない.(たとえ利用可能であっても)\r
205          */\r
206         public void drawWallpaper(Graphics2D g, int w, int h, boolean noUseOffscreen) {\r
207                 // 背景色\r
208                 Color bgColor = getBackgroundColor();\r
209                 \r
210                 // 背景色で塗りつぶす\r
211                 // (壁紙がある場合は不要)\r
212                 if (wallpaperImg == null) {\r
213                         fillBackgroundColor(g, bgColor, w, h);\r
214                 }\r
215                 \r
216                 // 壁紙を敷き詰める\r
217                 if (wallpaperImg != null) {\r
218                         // オフスクリーンによる背景描画が行われたか?\r
219                         boolean drawOffscreen = false;\r
220 \r
221                         if ( !noUseOffscreen) {\r
222                                 // オフクリーンサーフェイスのチェックまたは生成\r
223                                 AppConfig appConfig = AppConfig.getInstance();\r
224                                 if (appConfig.isEnableOffscreenWallpaper()) {\r
225                                         checkOrCreateOffscreen(g, bgColor, w, h);\r
226                                 } else {\r
227                                         disposeOffscreen();\r
228                                 }\r
229 \r
230                                 // オフスクリーンフェイスが有効であれば、オフスクリーンで描画する.\r
231                                 if (wallpaperVolatileImg != null) {\r
232                                         int src_w = wallpaperVolatileImg.getWidth();\r
233                                         int src_h = wallpaperVolatileImg.getHeight();\r
234                                         drawWallpaper(g, w, h, wallpaperVolatileImg, src_w, src_h);\r
235 \r
236                                         // オフスクリーンがロストしていなければ\r
237                                         // オフスクリーンで描画されたと判定する.\r
238                                         drawOffscreen = !wallpaperVolatileImg.contentsLost();\r
239                                 }\r
240                         }\r
241 \r
242                         // オフスクリーンサーフェイスで描画されていなければ通常の画像で描画する.\r
243                         if ( !drawOffscreen) {\r
244                                 if (wallpaperVolatileImg != null && logger.isLoggable(Level.INFO)) {\r
245                                         logger.log(Level.INFO, "offscreen is lost.");\r
246                                 }\r
247 \r
248                                 fillBackgroundColor(g, bgColor, w, h);\r
249 \r
250                                 Composite oldcomp = g.getComposite();\r
251                                 try {\r
252                                         float alpha = getWallpaperAlpha();\r
253                                         if (alpha < 1.f) {\r
254                                                 // アルファが100%の場合は、あえて設定しない.\r
255                                                 AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);\r
256                                                 g.setComposite(comp);\r
257                                         }\r
258                                         \r
259                                         int src_w = wallpaperImg.getWidth();\r
260                                         int src_h = wallpaperImg.getHeight();\r
261                                         drawWallpaper(g, w, h, wallpaperImg, src_w, src_h);\r
262 \r
263                                 } finally {\r
264                                         g.setComposite(oldcomp);\r
265                                 }\r
266                         }\r
267                 }\r
268         }\r
269 \r
270         /**\r
271          * 現在使用しているオフスクリーン用ネイティブリソースを破棄する.<br>\r
272          */\r
273         protected void disposeOffscreen() {\r
274                 if (wallpaperVolatileImg != null) {\r
275                         wallpaperVolatileImg.flush();\r
276                         wallpaperVolatileImg = null;\r
277 \r
278                         if (logger.isLoggable(Level.FINER)) {\r
279                                 logger.log(Level.FINER, "オフスクリーンを破棄しました。");\r
280                         }\r
281                 }\r
282         }\r
283         \r
284         /**\r
285          * オフスクリーンイメージが有効であるかチェックし、\r
286          * 有効でなければオフスクリーンを再作成、もしくは再描画する.<br>\r
287          * オフスクリーンは背景画像と同じサイズで作成される.<br>\r
288          * 背景画像が設定されていなければオフスクリーンも無効とする.<br>\r
289          * @param g 実際のスクリーンデバイス(互換性あるオフスクリーンを作成するため)\r
290          * @param bgColor 背景色\r
291          * @param offscreen_max_w オフスクリーンの最大サイズ(幅)\r
292          * @param offscreen_max_h オフスクリーンの最大サイズ(高さ)\r
293          */\r
294         protected void checkOrCreateOffscreen(Graphics2D g, Color bgColor, int offscreen_max_w, int offscreen_max_h) {\r
295                 if (wallpaperImg == null) {\r
296                         // 壁紙もと画像がなければ何もしない.\r
297                         disposeOffscreen();\r
298                         return;\r
299                 }\r
300                 try {\r
301                         GraphicsConfiguration gConf = g.getDeviceConfiguration();\r
302         \r
303                         // オフスクリーンの状態を確認する.\r
304                         int validate = VolatileImage.IMAGE_INCOMPATIBLE;\r
305                         if (wallpaperVolatileImg != null) {\r
306                                 validate = wallpaperVolatileImg.validate(gConf);\r
307                                 if (logger.isLoggable(Level.FINEST)) {\r
308                                         logger.log(Level.FINEST, "オフスクリーンの状態: "  + validate);\r
309                                 }\r
310                         }\r
311                         \r
312                         // 構築時の背景色と変更があるか?\r
313                         if (validate == VolatileImage.IMAGE_OK\r
314                                         && (wallpaperVolatileBgColor != null && bgColor != null)) {\r
315                                 if ( !wallpaperVolatileBgColor.equals(bgColor)) {\r
316                                         validate = VolatileImage.IMAGE_RESTORED;\r
317                                 }\r
318                         }\r
319                         \r
320                         // 壁紙元画像サイズ\r
321                         int src_w = wallpaperImg.getWidth();\r
322                         int src_h = wallpaperImg.getHeight();\r
323 \r
324                         // オフスクリーンサイズの算定.\r
325                         // 要求された最大幅かアプリ設定の最大幅の小さいほうを最大幅とし、\r
326                         // それが壁紙もと画像よりも小さければ壁紙サイズと同じとする.\r
327                         AppConfig appConfig = AppConfig.getInstance();\r
328                         int offscreen_w = appConfig.getOffscreenWallpaperSize();\r
329                         int offscreen_h = appConfig.getOffscreenWallpaperSize();\r
330                         \r
331                         offscreen_w = Math.max(src_w, Math.min(offscreen_max_w, offscreen_w));\r
332                         offscreen_h = Math.max(src_h, Math.min(offscreen_max_h, offscreen_h));\r
333                         \r
334                         // ブロックサイズを満たすために必要な元サイズの繰り返し数\r
335                         int nx = (int) ceil((double) offscreen_w / src_w);\r
336                         int ny = (int) ceil((double) offscreen_h / src_h);\r
337                         \r
338                         // 繰り返し数からブロックサイズに近い元サイズで割り切れるサイズを求める\r
339                         offscreen_w = src_w * nx;\r
340                         offscreen_h = src_h * ny;\r
341 \r
342                         // オフスクリーンが有効、もしくは描画が必要である状態の場合にサイズのチェックを行う.\r
343                         if (validate == VolatileImage.IMAGE_OK || validate == VolatileImage.IMAGE_RESTORED) {\r
344                                 int currentOffW = Math.max(1, wallpaperVolatileImg.getWidth());\r
345                                 int currentOffH = Math.max(1, wallpaperVolatileImg.getHeight());\r
346                                 \r
347                                 double ratioW = ((double) offscreen_w / currentOffW);\r
348                                 double ratioH = ((double) offscreen_h / currentOffH);\r
349                                 \r
350                                 // オフスクリーンの描画済みサイズが要求サイズの2割を超えるか割り込んだ場合は\r
351                                 // 再作成が必要.\r
352                                 if (ratioW < 0.8 || ratioW > 1.2 || ratioH < 0.8 || ratioH > 1.2) {\r
353                                         validate = VolatileImage.IMAGE_INCOMPATIBLE;\r
354 \r
355                                         if (logger.isLoggable(Level.FINE)) {\r
356                                                 logger.log(Level.FINE, "オフスクリーンサイズの変更が必要です。: " + ratioW + "," + ratioH);\r
357                                         }\r
358                                 }\r
359                         }\r
360                         \r
361                         // オフスクリーンの状態が再構築または再描画が必要であるか?\r
362                         if (validate != VolatileImage.IMAGE_OK ) {\r
363 \r
364                                 // オフスクリーンがないか、コンパチでなくなっている場合はオフスクリーンを生成する.\r
365                                 if (wallpaperVolatileImg == null || validate == VolatileImage.IMAGE_INCOMPATIBLE) {\r
366                                         // 現在使用しているネイティブリソースを破棄する.\r
367                                         disposeOffscreen();\r
368 \r
369                                         // 新しいオフスクリーンサーフェイスを作成する.\r
370                                         wallpaperVolatileImg = gConf.createCompatibleVolatileImage(\r
371                                                         offscreen_w, offscreen_h, Transparency.OPAQUE);\r
372                                         \r
373                                         if (wallpaperVolatileImg == null) {\r
374                                                 logger.log(Level.INFO, "オフスクリーンイメージは生成できません。");\r
375 \r
376                                         } else {\r
377                                                 if (logger.isLoggable(Level.FINER)) {\r
378                                                         logger.log(Level.FINER, "オフスクリーンを構築しました。(サイズ:"\r
379                                                                         + offscreen_w + "," + offscreen_h + ")");\r
380                                                 }\r
381                                         }\r
382                                 }\r
383 \r
384                                 // 再描画する.\r
385                                 if (wallpaperVolatileImg != null) {\r
386                                         if (logger.isLoggable(Level.FINER)) {\r
387                                                 logger.log(Level.FINER, "オフスクリーンの描画 (サイズ:"\r
388                                                                 + offscreen_w + "," + offscreen_h + ")");\r
389                                         }\r
390                                         \r
391                                         Graphics2D vg = wallpaperVolatileImg.createGraphics();\r
392                                         try {\r
393                                                 int ow = wallpaperVolatileImg.getWidth();\r
394                                                 int oh = wallpaperVolatileImg.getHeight();\r
395 \r
396                                                 fillBackgroundColor(vg, bgColor, ow, oh);\r
397 \r
398                                                 Composite oldcomp = vg.getComposite();\r
399                                                 try {\r
400                                                         float alpha = getWallpaperAlpha();\r
401                                                         if (alpha < 1.f) {\r
402                                                                 // アルファが100%の場合は、あえて設定しない.\r
403                                                                 AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);\r
404                                                                 vg.setComposite(comp);\r
405                                                         }\r
406 \r
407                                                         drawWallpaper(vg, ow, oh, wallpaperImg, src_w, src_h);\r
408                                                         \r
409                                                 } finally {\r
410                                                         vg.setComposite(oldcomp);\r
411                                                 }\r
412                                                 \r
413                                         } finally {\r
414                                                 vg.dispose();\r
415                                         }\r
416                                         \r
417                                         wallpaperVolatileBgColor = bgColor;\r
418                                 }\r
419                         }\r
420                         \r
421                 } catch (RuntimeException ex) {\r
422                         logger.log(Level.SEVERE, "オフスクリーンイメージの生成中に例外が発生しました。", ex);\r
423                         // 現在使用しているネイティブリソースを破棄する.\r
424                         disposeOffscreen();\r
425                 }\r
426         }\r
427 \r
428         /**\r
429          * 背景色で塗りつぶす\r
430          * @param g 対象\r
431          * @param bgColor 背景色、nullの場合は何もしない.\r
432          * @param w 幅\r
433          * @param h 高さ\r
434          */\r
435         protected void fillBackgroundColor(Graphics2D g, Color bgColor, int w, int h) {\r
436                 if (bgColor == null) {\r
437                         return;\r
438                 }\r
439                 Color oldc = g.getColor();\r
440                 try {\r
441                         Rectangle clip = g.getClipBounds();\r
442                         if (clip == null) {\r
443                                 clip = new Rectangle(0, 0, w, h);\r
444                         }\r
445                         g.setColor(bgColor);\r
446                         g.fill(clip);\r
447                         \r
448                 } finally {\r
449                         g.setColor(oldc);\r
450                 }\r
451         }\r
452         \r
453         /**\r
454          * 壁紙を指定の領域まで敷き詰めて描画する.<br>\r
455          * @param g\r
456          * @param w 敷き詰めるサイズ(幅)\r
457          * @param h 敷き詰めるサイズ(高さ)\r
458          * @param wallpaperImg 敷き詰める画像\r
459          * @param src_w 壁紙画像のサイズ\r
460          * @param src_v 壁紙画像の高さ\r
461          */\r
462         protected void drawWallpaper(Graphics2D g, int w, int h, Image wallpaperImg, int src_w, int src_h) {\r
463                 if (wallpaperImg == null) {\r
464                         return;\r
465                 }\r
466                 \r
467                 // 表示範囲で表示できる壁紙を表示できる個数\r
468                 int nx = (int) ceil((double) w / src_w);\r
469                 int ny = (int) ceil((double) h / src_h);\r
470                 \r
471                 // 描画対象領域\r
472                 Rectangle clip = g.getClipBounds();\r
473 \r
474                 // 描画対象領域にかかる壁紙を描画する. \r
475                 Rectangle rct = new Rectangle(0, 0, src_w, src_h);\r
476                 for (int iy = 0; iy <= ny; iy++) {\r
477                         for (int ix = 0; ix <= nx; ix++) {\r
478                                 rct.x = ix * src_w;\r
479                                 rct.y = iy * src_h;\r
480                                 if (clip == null || clip.intersects(rct)) {\r
481                                         g.drawImage(\r
482                                                         wallpaperImg,\r
483                                                         rct.x, rct.y,\r
484                                                         rct.x + rct.width, rct.y + rct.height,\r
485                                                         0, 0,\r
486                                                         src_w, src_h,\r
487                                                         null\r
488                                                         );\r
489                                 }\r
490                         }\r
491                 }\r
492         }\r
493         \r
494         /**\r
495          * 壁紙を一定の大きさに敷き詰める.<br>\r
496          * すでに十分大きい場合は何もしない.<br>\r
497          * @param wallpaper 対象のイメージ\r
498          * @return 拡張後のイメージ、もしくは同じイメージ\r
499          */\r
500         protected BufferedImage makeExpandedWallpaper(BufferedImage wallpaper) {\r
501                 if (wallpaper == null) {\r
502                         return null;\r
503                 }\r
504 \r
505                 // 敷き詰める画像の元サイズ\r
506                 int src_w = wallpaper.getWidth();\r
507                 int src_h = wallpaper.getHeight();\r
508                 \r
509                 // ブロックサイズよりも元サイズが大きければ何もしない.\r
510                 if (src_w > wallpaperPreferredWidth && src_h > wallpaperPreferredHeight) {\r
511                         return wallpaper;\r
512                 }\r
513 \r
514                 // ブロックサイズを満たすために必要な元サイズの繰り返し数\r
515                 int nx = (int) ceil((double) wallpaperPreferredWidth / src_w);\r
516                 int ny = (int) ceil((double) wallpaperPreferredHeight / src_h);\r
517                 \r
518                 // 繰り返し数からブロックサイズに近い元サイズで割り切れるサイズを求める\r
519                 int w = src_w * nx;\r
520                 int h = src_h * ny;\r
521                 \r
522                 // ブロックサイズまで元画像を敷き詰める\r
523                 BufferedImage wallpaperNew = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);\r
524                 Graphics2D g = wallpaperNew.createGraphics();\r
525                 try {\r
526                         drawWallpaper(g, w, h, wallpaper, src_w, src_h);\r
527                         \r
528                 } finally {\r
529                         g.dispose();\r
530                 }\r
531                 \r
532                 return wallpaperNew;\r
533         }\r
534         \r
535         public void addPropertyChangeListener(PropertyChangeListener listener) {\r
536                 propertyChangeSupport.addPropertyChangeListener(listener);\r
537         }\r
538         \r
539         public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {\r
540                 propertyChangeSupport.addPropertyChangeListener(propertyName, listener);\r
541         }\r
542         \r
543         public void removePropertyChangeListener(PropertyChangeListener listener) {\r
544                 propertyChangeSupport.removePropertyChangeListener(listener);\r
545         }\r
546         \r
547         public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {\r
548                 propertyChangeSupport.removePropertyChangeListener(propertyName, listener);\r
549         }\r
550 }\r