3 import java.awt.AlphaComposite;
\r
4 import java.awt.Color;
\r
5 import java.awt.Dimension;
\r
6 import java.awt.Font;
\r
7 import java.awt.FontMetrics;
\r
8 import java.awt.Graphics;
\r
9 import java.awt.Graphics2D;
\r
10 import java.awt.Rectangle;
\r
11 import java.awt.RenderingHints;
\r
12 import java.awt.font.FontRenderContext;
\r
13 import java.awt.font.GlyphMetrics;
\r
14 import java.awt.font.GlyphVector;
\r
15 import java.awt.font.TextAttribute;
\r
16 import java.awt.geom.Point2D;
\r
17 import java.awt.image.BufferedImage;
\r
18 import java.util.ArrayList;
\r
19 import java.util.HashMap;
\r
20 import java.util.Map;
\r
22 import javax.swing.JButton;
\r
23 import javax.swing.JLabel;
\r
26 public class JTXTButton extends JLabel {
\r
28 private static final long serialVersionUID = 1L;
\r
30 /*******************************************************************************
\r
32 ******************************************************************************/
\r
37 public static enum FontStyle {
\r
42 private String name;
\r
44 private FontStyle(String name) {
\r
49 public String toString() {
\r
54 public String getId() {
\r
55 return super.toString();
\r
58 public static FontStyle get(String id) {
\r
59 for ( FontStyle fs : FontStyle.values() ) {
\r
60 if ( fs.getId().equals(id) ) {
\r
68 private static final float DRAWTAB = 2.0F;
\r
71 /*******************************************************************************
\r
73 ******************************************************************************/
\r
76 private BufferedImage image = null; // ビットマップ
\r
78 private int vrow; // 仮想座標縦位置
\r
79 private int vcolumn; // 仮想座標横位置
\r
80 private int vheight; // 仮想座標高さ
\r
81 private int vwidth; // 仮想座標幅
\r
84 private ProgDetailList tvd = null; // 番組情報そのまま
\r
87 private static boolean showStart = true;
\r
88 private static boolean splitEpno = false;
\r
89 private static boolean showDetail = true;
\r
90 private static float detailTab = 2.0F;
\r
92 private static Font defaultFont = new JLabel().getFont();
\r
94 private static Font titleFont = defaultFont;
\r
95 private static int titleFontSize = defaultFont.getSize();
\r
96 private static Color titleFontColor = Color.BLUE;
\r
97 private static int titleFontStyle = Font.BOLD;
\r
99 private static Font detailFont = defaultFont;
\r
100 private static int detailFontSize = defaultFont.getSize();
\r
101 private static Color detailFontColor = Color.DARK_GRAY;
\r
102 private static int detailFontStyle = defaultFont.getStyle();
\r
104 private static Font startFont = defaultFont;
\r
106 private static FontRenderContext frc = new FontRenderContext(null, RenderingHints.VALUE_TEXT_ANTIALIAS_ON, RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT);
\r
108 private static int columnWidth = 0;
\r
109 private static float heightMultiplier = 0;
\r
112 /*******************************************************************************
\r
114 ******************************************************************************/
\r
119 /*******************************************************************************
\r
121 ******************************************************************************/
\r
124 // setVisible(false)するとリソースが解放されてしまうのか再描画に時間がかかるようになるので表示範囲外に出して隠してしまう
\r
125 public void clean() {
\r
128 setBounds(-1,-1,0,0);
\r
132 public void forceRepaint() {
\r
138 //public void setVRow(int n) { vrow = n; }
\r
139 public int getVRow() { return vrow; }
\r
140 //public void setVColumn(int n) { vcolumn = n; }
\r
141 public int getVColumn() { return vcolumn; }
\r
142 //public void setVHeight(int n) { vheight = n; }
\r
143 public int getVHeight() { return vheight; }
\r
145 public static void setColumnWidth(int n) { columnWidth = n; }
\r
146 public static void setHeightMultiplier(float f) { heightMultiplier = f; }
\r
148 public void setVBounds(int x, int y, int width, int height) {
\r
154 vcolumn*columnWidth,
\r
155 (int) Math.ceil(((float)vrow)*heightMultiplier),
\r
156 vwidth*columnWidth,
\r
157 (int) Math.ceil(((float)vheight)*heightMultiplier));
\r
160 public void reVBounds() {
\r
162 vcolumn*columnWidth,
\r
163 (int) Math.ceil(((float)vrow)*heightMultiplier),
\r
164 vwidth*columnWidth,
\r
165 (int) Math.ceil(((float)vheight)*heightMultiplier));
\r
169 public void setInfo(ProgDetailList tvd) {
\r
171 this.setText(null); // 簡易表示時代の名残
\r
173 this.setVerticalAlignment(JButton.TOP);
\r
174 this.setHorizontalAlignment(JButton.LEFT);
\r
175 //this.setBorder(new LineBorder(Color.BLACK,1));
\r
176 this.setOpaque(true);
\r
178 public ProgDetailList getInfo() {
\r
182 // 予約待機枠を表示するかどうかの確認
\r
183 public boolean isStandby() { return tvd.marked && tvd.showinstandby; }
\r
184 public boolean isStandbyByTrace() { return tvd.markedByTrace; }
\r
187 public static void setShowStart(boolean b) {
\r
190 public static void setSplitEpno(boolean b) {
\r
193 public static void setShowDetail(boolean b) {
\r
196 public static void setDetailTab(float n) {
\r
201 public static void setTitleFont(String fn) {
\r
202 if ( fn != null && ! fn.equals("") ) {
\r
203 Font f = new Font(fn,titleFontStyle,titleFontSize);
\r
209 //titleFont = this.getFont();
\r
211 public static void setTitleFontSize(int n) {
\r
213 titleFont = titleFont.deriveFont((float)titleFontSize);
\r
215 public static void setTitleFontColor(Color c) {
\r
216 titleFontColor = c;
\r
218 public static void setDetailFont(String fn) {
\r
219 if ( fn != null && ! fn.equals("") ) {
\r
220 Font f = new Font(fn,detailFontStyle,detailFontSize);
\r
223 startFont = f.deriveFont(Font.BOLD);
\r
227 //detailFont = new JLabel().getFont();
\r
229 public static void setDetailFontSize(int n) {
\r
230 detailFontSize = n;
\r
231 detailFont = detailFont.deriveFont((float)detailFontSize);
\r
232 startFont = startFont.deriveFont((float)detailFontSize);
\r
234 public static void setDetailFontColor(Color c) {
\r
235 detailFontColor = c;
\r
239 public static void setTitleFontStyle(ArrayList<FontStyle> fsa) {
\r
240 titleFont = setFontStyle(titleFont, (float)titleFontSize, fsa);
\r
242 public static void setDetailFontStyle(ArrayList<FontStyle> fsa) {
\r
243 detailFont = setFontStyle(detailFont, (float)detailFontSize, fsa);
\r
246 private static Font setFontStyle(Font f, float size, ArrayList<FontStyle> fsa) {
\r
247 Map<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>();
\r
248 attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_REGULAR);
\r
249 attributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_REGULAR);
\r
250 attributes.remove(TextAttribute.UNDERLINE);
\r
251 for ( FontStyle fs : fsa ) {
\r
254 attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
\r
257 attributes.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
\r
260 attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);//LOW_ONE_PIXEL);
\r
264 attributes.put(TextAttribute.SIZE, size);
\r
265 return f.deriveFont(attributes);
\r
269 public static void setAAHint(Object o) {
\r
270 frc = new FontRenderContext(null, o, RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT);
\r
274 /*******************************************************************************
\r
276 ******************************************************************************/
\r
282 protected void paintComponent(Graphics g) {
\r
284 super.paintComponent(g);
\r
287 if (image == null) {
\r
289 Dimension d = getSize();
\r
290 int imgw = d.width;
\r
291 int imgh = d.height;
\r
293 float draww = (float)imgw-DRAWTAB*2.0F;
\r
294 float drawh = (float)imgh;
\r
296 image = new BufferedImage(imgw, imgh, BufferedImage.TYPE_INT_ARGB);
\r
297 Graphics2D g2 = (Graphics2D)image.createGraphics();
\r
299 g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_SPEED);
\r
300 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
\r
302 float baseline = 0.0F;
\r
305 if (showStart && tvd.start != null && tvd.start.length() > 0) {
\r
306 FontMetrics fm = g2.getFontMetrics(startFont);
\r
307 float hi = Float.valueOf(fm.getHeight());
\r
308 float as = Float.valueOf(fm.getAscent());
\r
310 float startx = Float.valueOf(DRAWTAB);
\r
311 float startw = draww;
\r
312 float xposstartx = 0.0F;
\r
314 baseline = as; // 初期垂直位置
\r
317 WrappedGlyphVector wgv = getWrappedGlyphVector(tvd.start, startw, xposstartx, startFont, as, frc);
\r
318 GlyphVector gv = wgv.getGv();
\r
319 g2.setPaint(Color.BLACK);
\r
320 g2.drawGlyphVector(gv, startx, baseline);
\r
322 xposstartx = wgv.getLastX(); // 後続有り
\r
323 baseline += wgv.getLastY();
\r
327 WrappedGlyphVector wgv = getWrappedGlyphVector(" "+tvd.extension_mark, startw, xposstartx, startFont, as, frc);
\r
328 GlyphVector gv = wgv.getGv();
\r
329 g2.setPaint(Color.RED);
\r
330 g2.drawGlyphVector(gv, startx, baseline);
\r
332 baseline += wgv.getLastY();
\r
339 String title = ( splitEpno ) ? tvd.splitted_title : tvd.title;
\r
340 if ( title.length() > 0 ) {
\r
343 if (showStart && tvd.start.length() > 0) {
\r
344 aMark = tvd.prefix_mark + tvd.newlast_mark;
\r
347 if (tvd.start.length() > 0) {
\r
348 aMark = tvd.extension_mark + tvd.prefix_mark + tvd.newlast_mark;
\r
351 aMark = tvd.prefix_mark + tvd.newlast_mark;
\r
355 FontMetrics fm = g2.getFontMetrics(titleFont);
\r
356 float hi = Float.valueOf(fm.getHeight());
\r
357 float as = Float.valueOf(fm.getAscent());
\r
359 float titlex = Float.valueOf(DRAWTAB);
\r
360 float titlew = draww;
\r
363 if ( baseline == 0.0F ) {
\r
364 baseline = as; // 初期垂直位置
\r
367 if ( aMark.length() > 0 ) {
\r
368 WrappedGlyphVector wgv = getWrappedGlyphVector(aMark, titlew, xpos, titleFont, as, frc);
\r
369 GlyphVector gv = wgv.getGv();
\r
370 g2.setPaint(Color.RED);
\r
371 g2.drawGlyphVector(gv, titlex, baseline);
\r
373 xpos = wgv.getLastX(); // 後続有り
\r
374 baseline += wgv.getLastY();
\r
378 WrappedGlyphVector wgv = getWrappedGlyphVector(title+tvd.postfix_mark, titlew, xpos, titleFont, as, frc);
\r
379 GlyphVector gv = wgv.getGv();
\r
380 g2.setPaint(titleFontColor);
\r
382 drawString(g2, wgv, titlex, baseline);
\r
384 baseline += wgv.getLastY();
\r
391 if ( showDetail ) {
\r
394 detail = tvd.splitted_detail;
\r
397 detail = tvd.detail;
\r
400 FontMetrics fm = g2.getFontMetrics(detailFont);
\r
401 float as = Float.valueOf(fm.getAscent());
\r
402 float detailx = Float.valueOf(DRAWTAB+detailTab);
\r
403 float detailw = draww-detailTab;
\r
405 if ( baseline == 0.0F ) {
\r
406 baseline = as; // 初期垂直位置
\r
409 WrappedGlyphVector wgv = getWrappedGlyphVector(detail, detailw, 0.0f, detailFont, as, frc);
\r
410 g2.setPaint(detailFontColor);
\r
412 drawString(g2, wgv, detailx, baseline);
\r
417 g.drawImage(image, 0, 0, this);
\r
423 private void drawString(Graphics2D g2, WrappedGlyphVector wgv, float x, float y) {
\r
424 g2.drawGlyphVector(wgv.getGv(), x, y);
\r
426 if ( wgv.getGv().getFont().getAttributes().get(TextAttribute.UNDERLINE) != null ) {
\r
427 for ( Rectangle r : wgv.getLinePositions() ) {
\r
428 g2.drawLine((int)x+r.x, (int)y+r.y+1, (int)x+r.x+r.width-1, (int)y+r.y+1);
\r
434 * 参考:てんぷらメモ/JTableのセル幅で文字列を折り返し ( http://terai.xrea.jp/Swing/TableCellRenderer.html )
\r
435 * @param str 描画する文字列
\r
436 * @param width 描画領域の幅
\r
437 * @param xstart 1行目の描画開始位置
\r
438 * @param font 描画フォント
\r
439 * @param lineHeight 1行あたりの高さ
\r
440 * @param frc FontRenderContext
\r
443 private WrappedGlyphVector getWrappedGlyphVector(String str, float width, float xstart, Font font, float lineHeight, FontRenderContext frc) {
\r
444 Point2D gmPos = new Point2D.Double(0.0d, 0.0d);
\r
445 GlyphVector gv = font.createGlyphVector(frc, str);
\r
446 WrappedGlyphVector wgv = new WrappedGlyphVector(gv);
\r
447 float xpos = xstart;
\r
449 float advance = 0.0F;
\r
451 for( int i=0; i <= gv.getNumGlyphs(); i++ ) {
\r
452 if ( i == gv.getNumGlyphs() ) {
\r
453 int x = (int) ((ypos == 0.0F) ? xstart : 0.0F);
\r
454 int y = (int) ypos;
\r
455 int w = (int) (xpos - x);
\r
456 wgv.addLinePosition(new Rectangle(x, y, w, 1));
\r
459 gm = gv.getGlyphMetrics(i);
\r
460 advance = gm.getAdvance();
\r
461 if( xpos < width && width <= xpos+advance ) {
\r
462 int x = (int) ((ypos == 0.0F) ? xstart : 0.0F);
\r
463 int y = (int) ypos;
\r
464 int w = (int) (xpos - x);
\r
465 wgv.addLinePosition(new Rectangle(x, y, w, 1));
\r
466 ypos += lineHeight;
\r
469 gmPos.setLocation(xpos, ypos);
\r
470 gv.setGlyphPosition(i, gmPos);
\r
471 xpos = xpos + advance;
\r
473 wgv.setLastX(xpos);
\r
474 wgv.setLastY(ypos);
\r
479 private class WrappedGlyphVector {
\r
481 public WrappedGlyphVector(GlyphVector gv) {
\r
486 private GlyphVector gv;
\r
488 public GlyphVector getGv() { return gv; }
\r
490 private float lastx;
\r
491 private float lasty;
\r
493 public void setLastX(float x) { lastx = x; }
\r
494 public float getLastX() { return lastx; }
\r
495 public void setLastY(float y) { lasty = y; }
\r
496 public float getLastY() { return lasty; }
\r
498 private ArrayList<Rectangle> linePositions = new ArrayList<Rectangle>();
\r
499 public ArrayList<Rectangle> getLinePositions() { return linePositions; }
\r
500 public void addLinePosition(Rectangle r) { linePositions.add(r); }
\r