001 /*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016 package org.opengion.plugin.view;
017
018 import org.opengion.hayabusa.common.HybsSystem;
019 import org.opengion.hayabusa.common.HybsSystemException;
020 import org.opengion.fukurou.util.StringUtil;
021
022 import java.util.Calendar;
023 import java.util.Map;
024 import java.util.TreeMap;
025 import java.util.Collection;
026 import java.util.Locale ;
027 import java.util.Date;
028 import java.text.DateFormat;
029 import java.text.SimpleDateFormat;
030
031 import java.awt.Graphics2D;
032 import java.awt.Color;
033 import java.awt.FontMetrics;
034 import java.awt.Stroke;
035 import java.awt.BasicStroke;
036 import java.awt.image.BufferedImage;
037
038 import javax.imageio.ImageIO;
039 import java.io.File;
040 import java.io.IOException;
041
042
043 /**
044 * キー、日時?状況コードを持つ稼働状況?表示を行うクラスです?
045 *
046 * パラメータが?な場合?、ViewTimeBarParamTag を使用してください?
047 *
048 * パラメータが設定されて???合?、ViewForm_ImageTimeBar の初期値が使用されます?
049 * (パラメータを使用するには、viewタグのuseParam 属?をtrueに設定する?があります?)
050 *
051 * SELECT??、キー、日時?状況コードが、???で、カラ??並び??、完?に固定です?
052 * よって、カラ?置を指定する??ありませんが?SELECT?自由に設定すること?
053 * 出来ませんので、ご注意く???
054 * こ?固定化に伴??WRITABLE ?も使用できません。(そもそも書き込み不可です?
055 * それ以降?カラ?つ?は、?部処?しては、使用して?せん?
056 * ただし?パラメータで、カラー色??ラベル表記部、イメージ重?合わせ?
057 * ポップア??表記?リンク表記に使えます?
058 *
059 * ??タの並び?ORDER BY)も?キー、日時?にしてください?
060 * ??タは、キー単位に?レコード作?されます??キーブレイク?その間?日時?に
061 * ??タを??ます?
062 *
063 * ??タの表示は、今?レコード?日時から?次のレコード?日時までを?の状態と
064 * して表します?今?レコードを表示するには、次のレコードが?になります?
065 * 画面表示は、表示開始日?minStartTime) から 表示期間(timeSpan)?表示します?
066 * 通常?始時刻は、表示開始時刻より前より始まり?次のレコードで、終?刻が決?
067 * されます?????タは、期間??で続いて?と仮定されます?
068 * ??タが存在しな??であれば、?存在しな?ータ」を作?してください?
069 *
070 * ImageTimeBar では、キーでまとめた値につ?、各状況コードをカラー化し、積み上げ
071 * 帯グラフ形式でPNG画像化します?
072 * こ?画像を、読み込?HTML を?力することで、画面上に、積み上げ帯グラフを表示します?
073 * 状況コードに対応する色は、標準では自動作?ですが、外部から色??(colorClm)を与えることで
074 * 自由に?する事も可能です?
075 *
076 * ポップア??表?tipsClm)、リンク表?linkClm)は、この画像に対するエリア?タグを?力する事で実現します?
077 * 画像ファイルは、???タに対して?画像だけなので、サイズは大きくなりますが?レコー?
078 * 単位に画像を作?しな?め?レスポンスは向上します?
079 * それぞれ、viewMarker , viewLink を利用することが可能です?特に、リンク表?linkClm) につ?は?
080 * linkタグの hrefTarget 属??true に設定することで適用できます?
081 *
082 * 画像ファイルは、java.io.File.createTempFile( File ) で作?するため、JavaVM(=Tomcat)?
083 * 正常終?るときに、削除されます?異常終?には残りますが、temp フォル?定期?
084 * 整?れ?、それほど大量?ファイルが残ることはな?思われます?
085 *
086 * ??タは、イベント発生時に作?されると仮定して?す?つまり?書き込まれた日時から?
087 * 状況コードに対応する状況が発生し、次の状???レコードまで継続して?と?ます?
088 * よって、データを?中で?出す?合??出す?の前?状態が?になります?
089 * ???の状態??不?" として扱?す??空?白色??
090 *
091 * @og.rev 5.5.5.6 (2012/08/31) 新規追?
092 * @og.group 画面表示
093 *
094 * @version 4.0
095 * @author Kazuhiko Hasegawa
096 * @since JDK5.0,
097 */
098 public class ViewForm_ImageTimeBar extends ViewForm_HTMLTable {
099 //* こ?プログラ??VERSION??を設定します? {@value} */
100 private static final String VERSION = "5.6.5.0 (2013/06/07)" ;
101
102 private static final Color LABEL_COLOR = Color.BLACK; // ラベル記述時?色
103 private static final Color NULL_COLOR = Color.WHITE; // 5.6.1.1 (2013/02/08) 不?(空?時?色
104
105 private long startDate ; // タイ?ーブルの表示開始日時から求め?long 値(1=??
106 private long timeSpan ; // タイ?ーブルの表示期間。?は時間?であるが??位で持つ?1=??
107
108 private boolean useLegend ; // カラーの凡例を使用するかど?[true/false]
109 private int maxLabelWidth ; // ラベル表記部の?サイズをpxで??何もなければ、可変長サイズ
110 private int maxTimeWidth ; // タイ?記部の?サイズをpxで??
111 private int chartHeight ; // ?レコード?チャート?間隔をpxで??実際の??、CHART_HEIGHT?MARGIN??
112 private int chartPadding ; // イメージ作?の 全体テーブルの隙間
113 private int recodeMargin ; // ?コード??等??の間隔
114 private boolean useLastData ; // 5.6.1.1 (2013/02/08) 行?????が?継続して?として使?ど?[true/false]
115
116 private String tempDir ; // 画像ファイルを作?する?ポラリ?レクトリ(相対パス)
117 private String tempUrl ; // 作?した画像ファイルを取得するときに使用するURL(コン?ス?相対パス)
118
119 // SELECT??、キー、日時?状況コードが、???
120 private static final int keyClmNo = 0; // ヘッ??1?キーカラ?o
121 private static final int dyClmNo = 1; // ヘッ??2?日時カラ?o
122 private static final int fgjClmNo = 2; // ヘッ??3?状況コードカラ?o
123
124 private int[] labelClmsNo = null; // 初期値は、キーカラ?
125 private int[] maxClmWidth = null; // labelClms 単位????長
126 private int colClmNo = -1; // カラーコード直接?する?合に色??を指定するカラ?o
127 private int tipsClmNo = -1; // マウスオーバ?時?Tips表示を行うカラ?o
128 private int linkClmNo = -1; // クリ?ブルリンクを設定するカラ?o
129
130 private int str2DateTime ; // getStr2Date(String)処?おこなった時の、引数の時刻??(??をセ?する?ポラリ変数?
131 private int startTime ; // startDate の時刻??。上記??、startDate ?getStr2Date(String) 処?たとき?値を持っておくための変数?
132
133 private int MAX_X ; // イメージの?横?X)方向?サイズpx。chartPadding*2 + maxLabelWidth + maxTimeWidth
134 private int MAX_Y ; // イメージの?縦?Y)方向?サイズpx。chartPadding*2 + (chartHeight+recodeMargin*2)*(レコード数???ー数)
135
136 /**
137 * ?をクリア(初期?します?
138 *
139 */
140 // @Override
141 // public void clear() {
142 // super.clear();
143 // }
144
145 /**
146 * DBTableModel から HTML??を作?して返します?
147 * startNo(表示開始位置)から、pageSize(表示件数)までのView??を作?します?
148 * 表示残り??タ?pageSize 以下?場合?,残りの??タをすべて出力します?
149 *
150 * @og.rev 5.6.1.0 (2013/02/01) tips ?link は、?とつ前???タで作?する?がる為、最初?1件目は、??な??修正
151 * @og.rev 5.6.1.1 (2013/02/08) 初期値の色を?直接の値ではなく?static final で定義された色を使用する。色自体?変えて?せん
152 * @og.rev 5.6.1.1 (2013/02/08) useLastData 追?
153 * @og.rev 5.6.3.0 (2013/04/01) tipsのシングルクォー??ション のエスケー?
154 * @og.rev 5.6.3.1 (2013/04/05) 短縮ラベルなど?lt;span>タグが付与される値から、spanタグを削除します?
155 *
156 * @param startNo 表示開始位置
157 * @param pageSize 表示件数
158 *
159 * @return DBTableModelから作?され?HTML??
160 */
161 @Override
162 public String create( final int startNo, final int pageSize ) {
163 if( getRowCount() == 0 ) { return ""; } // 暫定?置
164
165 // パラメータの??を?期化??得します?
166 paramInit();
167
168 int lastNo = getLastNo( startNo, pageSize );
169
170 // イメージの ???サイズを求め、結果を?MAX_X,MAX_Y 変数に設定する?
171 calcImageSize( startNo,lastNo );
172
173 BufferedImage img = new BufferedImage( MAX_X, MAX_Y, BufferedImage.TYPE_INT_ARGB);
174 Graphics2D g2 = img.createGraphics();
175
176 // chartPadding を?慮した領域のクリ???クリ??外にDrowされても無視されます???
177 g2.setClip( chartPadding , chartPadding , MAX_X-chartPadding*2+1 , MAX_Y-chartPadding*2+1 ); // ?? 座?y 座??高さ) ?1?罫線??
178
179 StringBuilder out = new StringBuilder( HybsSystem.BUFFER_LARGE );
180
181 String oldKeyVal = ""; // 初期値。1回目にキーブレイクさせる?
182 long oldTime = 0L; // 日付?目の?前?値
183
184 // Color oldColor = Color.WHITE; // 色の?前?値(初期値)
185 Color oldColor = NULL_COLOR; // 5.6.1.1 (2013/02/08) 不?(空?時?色(初期値)
186
187 ColorMap colMap = new ColorMap(); // 状況コード?ラベル、カラーを管?るクラス
188
189 int rowCnt = (useLegend) ? 2 : 1; // 凡?useLegend)を使?true)場合??行?、使わな??合?、??ーの?行が初期値
190 int imgX = 0; // イメージ出力時の X軸の左端 px数
191 int imgY = 0; // イメージ出力時の Y軸の上端 px数
192 int imgW = 0; // イメージ出力時の ?fillRectで使用)
193 int imgH = chartHeight; // イメージ出力時の 高さ(fillRectで使用)
194 int rowH = chartHeight+recodeMargin*2; // 罫線?力時の高さ(drawRectで使用)
195
196 double timeScale = (double)maxTimeWidth/(double)timeSpan;
197 boolean useTipsLink = (tipsClmNo >= 0 || linkClmNo >= 0) ; // tipsClm ?linkClm かどちらかを使用する場合?true
198 for( int row=startNo; row<lastNo; row++ ) {
199 // キーブレイクの判?
200 String keyVal = getValue( row,keyClmNo );
201 String dyVal = getValue( row,dyClmNo );
202
203 // キーブレイク判定?キーブレイクは、?初めから来る?
204 if( !oldKeyVal.equals( keyVal ) ) {
205 // キーブレイクで??に行うのは、前のレコード?未出力?の処???行目は、???
206 if( row > startNo ) {
207 imgX = chartPadding + maxLabelWidth + (int)(oldTime*timeScale);
208 imgW = (int)((timeSpan-oldTime)*timeScale) ;
209
210 // ?0以上?場合?み描画する?
211 if( imgW > 0 ) {
212 // 5.6.1.1 (2013/02/08) useLastData 追?
213 if( useLastData ) { g2.setColor( oldColor ); } // 色の設定?、旧色を使?
214 else { g2.setColor( NULL_COLOR ); } // NULL色を使?
215 g2.fillRect( imgX , imgY+recodeMargin , imgW, imgH ); // (実際の状?左端x,上端y,?,高さh
216
217 // tipsClm ?linkClm を使用する?
218 // 5.6.1.0 (2013/02/01) tips ?link は、?とつ前???タで作?する?がる為、最初?1件目は、??な??修正
219 // if( useTipsLink ) {
220 // if( useTipsLink && row > 0 ) {
221 if( useLastData && useTipsLink && row > 0 ) { // 5.6.1.1 (2013/02/08) useLastData 追?
222 // tips ?link は、?とつ前???タで作?する?がある?row-1)
223 String tips = (tipsClmNo >= 0) ? getValueLabel( row-1,tipsClmNo ) : getValueLabel( row-1,fgjClmNo ) ;
224 if( tips != null && tips.indexOf( "'" ) >= 0 ) { // 5.6.3.0 (2013/04/01) シングルクォー??ション のエスケー?
225 tips = tips.replaceAll( "'","'" );
226 }
227 tips = StringUtil.spanCut( tips ); // 5.6.3.1 (2013/04/05) spanタグを削除
228
229 out.append( "<area shape='rect' alt='" ).append( tips ).append( "'" );
230 if( linkClmNo >= 0 ) {
231 String hrefVal = getValueLabel( row-1,linkClmNo );
232 if( hrefVal != null && hrefVal.startsWith( "href" ) ) { // linkClmの値の先?が?html の場合?み追?る?
233 out.append( hrefVal );
234 }
235 }
236 out.append( " coords='" ).append( imgX ).append( "," ).append( imgY+recodeMargin ).append( "," ); // 左端x1,上端y1
237 out.append( imgX+imgW ).append( "," ).append( imgY+recodeMargin+chartHeight ).append( "' />" ); // 右端x2,下段y2
238 }
239 }
240 }
241
242 // 次に、新しい行?出力(ラベルは、ブレイク時に出力しておきます???
243 oldKeyVal = keyVal; // null は来な???
244 imgY = chartPadding+(rowH)*rowCnt ;
245 rowCnt++ ;
246
247 // レコード?ラベル?け?繰返し描画する?
248 int clmSu = labelClmsNo.length;
249 int posX = chartPadding ; // ラベル??の書き?し位置の初期値
250 int posY2 = imgY+chartHeight+recodeMargin ; // ラベルのY軸基準?
251 g2.setColor( LABEL_COLOR );
252 for( int col=0; col<clmSu; col++ ) {
253 String lbl = getValueLabel( row,labelClmsNo[col] ); // そ?行?値のRenderer値
254 lbl = StringUtil.spanCut( lbl ); // 5.6.3.1 (2013/04/05) spanタグを削除
255 g2.drawString( lbl , posX + recodeMargin, posY2 ); // ??,ベ?スラインのx座?y座?
256 posX += recodeMargin*2 + maxClmWidth[col] ; // 次の書き?し位置は、文字最大長??ージン
257 }
258
259 // レコード???
260 g2.drawRect( chartPadding , imgY , MAX_X-chartPadding*2 , rowH ); // (レコード枠)左端x,上端y,?,高さh
261
262 oldTime = 0L; // キーブレイクによる初期?
263 // oldColor= Color.WHITE; // キーブレイクによる初期?
264 oldColor= NULL_COLOR; // 5.6.1.1 (2013/02/08) キーブレイクによる初期?不?(空?時?色
265 }
266
267 long newTime = getStr2Date( dyVal ) - startDate; // 次の時刻
268 if( newTime < oldTime ) { newTime = oldTime; } // 前?時刻より小さ??合?、前の時刻まで??めておく?
269
270 imgX = chartPadding + maxLabelWidth + (int)(oldTime*timeScale); // old時刻から書き始め?左端x)
271 imgW = (int)((newTime-oldTime)*timeScale) ; // 差??け描画する?
272
273 // ?0以上?場合?み描画する?
274 if( imgW > 0 ) {
275 g2.setColor( oldColor ); // 色の設?
276 g2.fillRect( imgX , imgY+recodeMargin , imgW, chartHeight ); // (実際の状?左端x,上端y,?,高さh
277
278 // tipsClm ?linkClm を使用する?
279 // 5.6.1.0 (2013/02/01) tips ?link は、?とつ前???タで作?する?がる為、最初?1件目は、??な??修正
280 // if( useTipsLink ) {
281 if( useTipsLink && row > 0 ) {
282 // tips ?link は、?とつ前???タで作?する?がある?row-1)
283 String tips = (tipsClmNo >= 0) ? getValueLabel( row-1,tipsClmNo ) : getValueLabel( row-1,fgjClmNo ) ;
284 if( tips != null && tips.indexOf( "'" ) >= 0 ) { // 5.6.3.0 (2013/04/01) シングルクォー??ション のエスケー?
285 tips = tips.replaceAll( "'","'" );
286 }
287 tips = StringUtil.spanCut( tips ); // 5.6.3.1 (2013/04/05) spanタグを削除
288
289 out.append( "<area shape='rect' alt='" ).append( tips ).append( "'" );
290 if( linkClmNo >= 0 ) {
291 String hrefVal = getValueLabel( row-1,linkClmNo );
292 if( hrefVal != null && hrefVal.startsWith( "href" ) ) { // linkClmの値の先?が?html の場合?み追?る?
293 out.append( hrefVal );
294 }
295 }
296 out.append( " coords='" ).append( imgX ).append( "," ).append( imgY+recodeMargin ).append( "," ); // 左端x1,上端y1
297 out.append( imgX+imgW ).append( "," ).append( imgY+recodeMargin+chartHeight ).append( "' />" ); // 右端x2,下段y2
298 }
299 }
300
301 oldTime = newTime ;
302
303 String fgjVal = getValue( row,fgjClmNo ); // 状況コード?キー
304 String fgjLbl = getValueLabel( row,fgjClmNo ); // 状況コード?ラベル
305 if( colClmNo >= 0 ) {
306 oldColor = colMap.getColor( fgjVal,fgjLbl,getValue( row,colClmNo ) ); // 色??を指定する??
307 }
308 else {
309 oldColor = colMap.getColor( fgjVal,fgjLbl ); // 色??を指定しな??動設?
310 }
311 }
312
313 // レコード??ばん最後?出力???ジャスト?場?oldTime == maxEdTime)は、??な?
314 // 5.6.1.1 (2013/02/08) レコード??ばん最後?出力?、NULL色を使??変更
315 if( oldTime < timeSpan ) {
316 imgX = chartPadding + maxLabelWidth + (int)(oldTime*timeScale);
317 imgW = (int)((timeSpan-oldTime)*timeScale) ;
318 // 5.6.1.1 (2013/02/08) useLastData 追?
319 if( useLastData ) { g2.setColor( oldColor ); } // 色の設定?、旧色を使?
320 else { g2.setColor( NULL_COLOR ); } // NULL色を使?
321 g2.fillRect( imgX , imgY+recodeMargin , imgW, chartHeight ); // (実際の状?左端,上端,?高さ
322
323 // tipsClm ?linkClm を使用する?
324 // if( useTipsLink ) {
325 if( useLastData && useTipsLink ) { // 5.6.1.1 (2013/02/08) useLastData 追?
326 // tips ?link ??出力?、最後???タなので、lastNo-1 となる?
327 String tips = (tipsClmNo >= 0) ? getValueLabel( lastNo-1,tipsClmNo ) : getValueLabel( lastNo-1,fgjClmNo ) ;
328 if( tips != null && tips.indexOf( "'" ) >= 0 ) { // 5.6.3.0 (2013/04/01) シングルクォー??ション のエスケー?
329 tips = tips.replaceAll( "'","'" );
330 }
331 tips = StringUtil.spanCut( tips ); // 5.6.3.1 (2013/04/05) spanタグを削除
332
333 out.append( "<area shape='rect' alt='" ).append( tips ).append( "'" );
334 if( linkClmNo >= 0 ) {
335 String hrefVal = getValueLabel( lastNo-1,linkClmNo );
336 if( hrefVal != null && hrefVal.startsWith( "href" ) ) { // linkClmの値の先?が?html の場合?み追?る?
337 out.append( hrefVal );
338 }
339 }
340 out.append( " coords='" ).append( imgX ).append( "," ).append( imgY+recodeMargin ).append( "," ); // 左端x1,上端y1
341 out.append( imgX+imgW ).append( "," ).append( imgY+recodeMargin+chartHeight ).append( "' />" ); // 右端x2,下段y2
342 }
343 }
344
345 // ヘッ????のイメージを作?します?
346 imageHeaderPaint( g2 , timeScale , colMap );
347
348 // イメージファイルを?力し、URLを返します?
349 File file = null;
350 try {
351 File dir = new File( tempDir ); // 画像ファイル出力?のフォル?
352 dir.mkdirs(); // なければ作?する?
353
354 file = File.createTempFile( "Img",".png", dir ); // ?ポラリファイルの作?
355 file.deleteOnExit(); // JavaVM 停止時に?ポラリファイルの削除
356
357 ImageIO.write(img, "PNG", file );
358 g2.dispose();
359 }
360 catch( IOException ex ) {
361 System.out.println( "エラー:" + ex );
362 }
363
364 // imgタグを作?します?
365 int width = MAX_X;
366 int height = MAX_Y;
367
368 StringBuilder out2 = new StringBuilder( HybsSystem.BUFFER_LARGE );
369 out2.append( "<img id='ImageTimeBar' alt='ImageTimeBar' border='0'" );
370 out2.append( " width='" ).append( width ).append( "px' height='" ).append( height ).append( "px'" );
371 out2.append( " src='" ).append( tempUrl ).append( file.getName() ).append( "'" );
372
373 // area タグの??タが作?されて?ば、?力します?
374 if( out.length() > 0 ) {
375 out2.append( " usemap='#TimeBarMap' />" ); // img タグにusemap 属?を追?て、終??追?
376
377 out2.append( "<map name='TimeBarMap'>" );
378 out2.append( out );
379 out2.append( "</map>" );
380 }
381 else {
382 out2.append( " />" ); // img タグの終??追?
383 }
384
385 return out2.toString();
386 }
387
388 /**
389 * パラメータ?を?期化します?
390 *
391 * @og.rev 5.6.1.1 (2013/02/08) useLastData 追?
392 */
393 private void paramInit() {
394 String s_startDate = getParam( "START_DATE" ); // タイ?ーブルの表示開始日時をセ?しま?初期値:??タの?日??
395 int timeSpanHour = getIntParam( "TIME_SPAN" ); // タイ?ーブルの表示期間を時間で?しま?初期値:{@og.value TIME_SPAN})?
396
397 String[] s_labelClms = StringUtil.csv2Array( getParam( "LABEL_CLMS" ) ); // ?表のラベル表示部に表示するカラ?をCSV形式で?します?
398 String s_colClm = getParam( "COLOR_CLM" ); // レコードに付ける色を色??で?する?合?カラ?を指定します?
399 String s_tipsClm = getParam( "TIPS_CLM" ); // レコード単位に、?ウスオーバ?時?Tips表示を行うカラ?を指定します?
400 String s_linkClm = getParam( "LINK_CLM" ); // レコード単位に、クリ?ブルリンクを設定するカラ?を指定します?
401
402 useLegend = getBoolParam( "USE_LEGEND" ); // カラーの凡例を使用するかど?[true/false]
403 maxLabelWidth = getIntParam( "MAX_LABEL_WIDTH" ); // ラベル表記部の?サイズをpxで??何もなければ、可変長サイズ
404 maxTimeWidth = getIntParam( "MAX_TIME_WIDTH" ); // タイ?記部の?サイズをpxで??
405 chartHeight = getIntParam( "CHART_HEIGHT" ); // ?レコード?チャート?間隔をpxで??実際の??、CHART_HEIGHT?MARGIN??
406 chartPadding = getIntParam( "CHART_PADDING" ); // イメージ作?の 全体テーブルの隙間
407 recodeMargin = getIntParam( "RECODE_MARGIN" ); // ?コード??等??の間隔
408 useLastData = getBoolParam( "USE_LAST_DATA" ); // 5.6.1.1 (2013/02/08) 行?????が?継続して?として使?ど?[true/false]
409
410 tempDir = getParam( "TEMP_DIR" ); // 画像ファイルを作?する?ポラリ?レクトリ(相対パス)
411 tempUrl = getParam( "TEMP_URL" ); // 作?した画像ファイルを取得するときに使用するURL(コン?ス?相対パス)
412
413 startDate = getStr2Date( s_startDate ); // ?位に変換する?
414 startTime = str2DateTime ; // 開始日時?時刻??(??の値。str2DateTime は、getStr2Date(String)メソ?実行後にセ?される?
415 timeSpan = timeSpanHour * 60L ; // ?位に変換する?
416
417 int len = s_labelClms.length;
418 if( len > 0 ) {
419 labelClmsNo = new int[len];
420 for( int i=0; i<len; i++ ) {
421 labelClmsNo[i] = getColumnNo( s_labelClms[i] );
422 }
423 }
424 else {
425 labelClmsNo = new int[] { keyClmNo }; // 初期値は、キーカラ?
426 }
427
428 // ??カラ?に対するカラ?号を取得?なければ?1 を設定しておく?
429 if( s_colClm != null ) { colClmNo = getColumnNo( s_colClm ); } // レコードに付ける色を色??で?する?合?カラ?o
430 if( s_tipsClm != null ) { tipsClmNo = getColumnNo( s_tipsClm ); } // レコード単位に、?ウスオーバ?時?Tips表示を行うカラ?o
431 if( s_linkClm != null ) { linkClmNo = getColumnNo( s_linkClm ); } // レコード単位に、クリ?ブルリンクを設定するカラ?o
432 }
433
434 /**
435 * イメージの ??サイズを求め、結果を?MAX_X,MAX_Y 変数に設定します?
436 *
437 * また?ラベル??の?長が指定されて???合?axLabelWidth == -1?最大長を?動計算し、maxLabelWidth変数にセ?します?
438 *
439 * maxLabelWidth : -1 の場合?、ラベル??の?長を求めて、この値を計算する?= (recodeMargin*2 + ラベル??の?長)
440 * MAX_X : イメージの?横?X)方向?サイズpx。chartPadding*2 + maxLabelWidth + maxTimeWidth
441 * MAX_Y : イメージの?縦?Y)方向?サイズpx。chartPadding*2 + (chartHeight+recodeMargin*2)*(レコード数???ー数)
442 *
443 * @og.rev 5.6.3.1 (2013/04/05) 短縮ラベルなど?span>タグが付与される値から、spanタグを削除します?
444 *
445 * @param startNo 計算?開始?番号
446 * @param lastNo 計算?終??番号
447 */
448 private void calcImageSize( final int startNo , final int lastNo ) {
449 String oldKeyVal = ""; // 初期値。1回目にキーブレイクさせる?
450
451 int clmSu = labelClmsNo.length;
452 maxClmWidth = new int[clmSu];
453
454 int rowCnt = (useLegend) ? 2 : 1; // 凡?useLegend)を使?true)場合??行?、使わな??合?、??ーの?行が初期値
455
456 // ラベル領域の長さを?ベル長を積み上げて計算する?
457 if( maxLabelWidth < 0 ) {
458 // FontMetrics を取得する為?の BufferedImage
459 BufferedImage img = new BufferedImage( 1, 1, BufferedImage.TYPE_INT_ARGB);
460 Graphics2D g2 = img.createGraphics();
461 FontMetrics fontM = g2.getFontMetrics();
462
463 // 初期値の計算?、??ーのラベルの?使用する?
464 for( int col=0; col<clmSu; col++ ) {
465 String lbl = getColumnLabel( labelClmsNo[col] ); // ヘッ??のラベル
466 lbl = StringUtil.spanCut( lbl ); // 5.6.3.1 (2013/04/05) spanタグを削除
467 maxClmWidth[col] = fontM.stringWidth( lbl ); // ?値の初期値として、??ーラベルの?セ?しておく?
468 }
469
470 for( int row=startNo; row<lastNo; row++ ) {
471 // キーブレイク判定?キーブレイクは、?初めから来る?
472 String keyVal = getValue( row,keyClmNo );
473 if( !oldKeyVal.equals( keyVal ) ) {
474 oldKeyVal = keyVal;
475 rowCnt++; // レコード数
476
477 // ラベルは、キーブレイク時?値のみ採用する?
478 for( int col=0; col<clmSu; col++ ) {
479 String lbl = getValueLabel( row,labelClmsNo[col] ); // そ?行?値のRenderer値
480 lbl = StringUtil.spanCut( lbl ); // 5.6.3.1 (2013/04/05) spanタグを削除
481 int fontW = fontM.stringWidth( lbl );
482 if( maxClmWidth[col] < fontW ) { maxClmWidth[col] = fontW; }
483 }
484 }
485 }
486 g2.dispose();
487
488 // ?ラベル??、各ラベルの?値?(?ージン?2)*カラ?
489 maxLabelWidth = recodeMargin * 2 * clmSu ;
490 for( int col=0; col<clmSu; col++ ) {
491 maxLabelWidth += maxClmWidth[col];
492 }
493 }
494 else {
495 for( int row=startNo; row<lastNo; row++ ) {
496 // キーブレイク判定?キーブレイクは、?初めから来る?
497 String keyVal = getValue( row,keyClmNo );
498 if( !oldKeyVal.equals( keyVal ) ) {
499 oldKeyVal = keyVal;
500 rowCnt++; // レコード数
501 }
502 }
503
504 // ?ラベル??、均等割り付け。端数は無視(ど?、ラベル部は、maxLabelWidth で計算する?で。?
505 int clmWidth = ( maxLabelWidth - recodeMargin * 2 * clmSu ) / clmSu ;
506 for( int col=0; col<clmSu; col++ ) {
507 maxClmWidth[col] = clmWidth;
508 }
509 }
510
511 MAX_X = chartPadding*2 + maxLabelWidth + maxTimeWidth ;
512 MAX_Y = chartPadding*2 + (chartHeight+recodeMargin*2)*rowCnt ;
513 }
514
515 /**
516 * ヘッ????のイメージを作?します?
517 *
518 * 全体??ここで作?しておきます?
519 * イメージは、キーカラ??ラベルと、時間軸になります?時間軸は縦方向にすべて線を引きます?
520 * 時間軸の間隔は、timeScale によって、?り替わります?
521 * 凡例を使??合?seLegend=true??、引数の ColorMap を利用して作?します?
522 *
523 * @og.rev 5.6.3.1 (2013/04/05) 短縮ラベルなど?span>タグが付与される値から、spanタグを削除します?
524 * @og.rev 5.6.5.0 (2013/06/07) 年月日??を表示します?なお?日単位?場合?、年月?省略します?
525 *
526 * @param g2 描画するGraphics2Dオブジェク?
527 * @param timeScale 時間(?当たり?ピクセル数
528 * @param colMap 状況コードに対応したカラーマッ?
529 */
530 private void imageHeaderPaint( final Graphics2D g2 , final double timeScale , final ColorMap colMap ) {
531
532 int posY1 = chartPadding ;
533 int posY2 = chartPadding+chartHeight+recodeMargin ;
534
535 // 凡例を使???
536 if( useLegend && colMap != null ) {
537 // 凡例を並べる間隔を求める?
538 FontMetrics fontM = g2.getFontMetrics();
539 int maxSize = fontM.stringWidth( colMap.getMaxLengthLabel() ) ; // ??の?長ラベルの?
540 int imgW = chartHeight ; // 凡例■の?高さと同じにして?ので真四?
541 int mgnW = recodeMargin ; // 凡例■から?までの?
542 int spanW = maxSize + recodeMargin ; // 凡例■から凡例■までの間隔。文字最大長?α
543
544 int legX = chartPadding ;
545 for( Object[] obj : colMap.values() ) {
546 String lbl = (String)obj[0];
547 Color col = (Color)obj[1];
548
549 g2.setColor( col ); // 凡例■の色
550 g2.fillRect( legX , posY1+recodeMargin , imgW , chartHeight ); // (実際の状?左端x,上端y,?,高さh
551
552 legX += imgW + mgnW ;
553 g2.setColor( LABEL_COLOR );
554 g2.drawString( lbl , legX , posY2 ); // ??,ベ?スラインのx座?y座?
555
556 legX += spanW ;
557 }
558 posY1 += chartHeight+recodeMargin*2 ; // ?レコード?の高さを加算しておく?
559 posY2 += chartHeight+recodeMargin*2 ; // ?レコード?の高さを加算しておく?
560 }
561
562 // まず?、?体???描画
563 g2.setColor( LABEL_COLOR );
564 g2.drawRect( chartPadding, posY1, MAX_X-chartPadding*2, MAX_Y-posY1-chartPadding ); // 左端,上端,?高さ
565
566 // ヘッ??のラベル?け?繰返し描画する?
567 int clmSu = labelClmsNo.length;
568 int posX = chartPadding ; // ラベル??の書き?し位置の初期値
569 for( int col=0; col<clmSu; col++ ) {
570 String lbl = getColumnLabel( labelClmsNo[col] ); // ヘッ??のラベル
571 lbl = StringUtil.spanCut( lbl ); // 5.6.3.1 (2013/04/05) spanタグを削除
572 g2.drawString( lbl , posX + recodeMargin, posY2 ); // ??,ベ?スラインのx座?y座?
573 posX += recodeMargin*2 + maxClmWidth[col] ; // 次の書き?し位置は、文字最大長??ージン*2
574 g2.drawLine( posX, posY1, posX, MAX_Y-chartPadding ); // 始点(x 座?y 座?,終点(x 座?y 座?
575 }
576
577 int step = TimeScaleStep.getStep( timeScale ); // 時間スケールに対応したSTEP数
578
579 // 日付??ー部の描画のためのカレン??
580 Calendar cal = Calendar.getInstance();
581 cal.setTimeInMillis( startDate * 60000L );
582
583 int week = cal.get( Calendar.DAY_OF_WEEK ); // 開始曜日
584
585 String fmt = ( step < 1440 ) ? "yyyy/MM/dd(EE)" : "dd" ; // 上段フォーマット?、時間?ースの場合??yyyy/MM/dd(EE)" 、日ベ?スの場合??dd"
586 DateFormat format1 = new SimpleDateFormat( fmt,Locale.JAPAN );
587
588 // グラフ?域?日付??ー部の描画
589 g2.setStroke( DSAH_STROK ); // 日付部は、??
590 posX = chartPadding+maxLabelWidth ; // グラフ?域?、chartPadding+maxLabelWidth から?
591 for( int tm = 0; tm < timeSpan; tm+=step ) {
592
593 int offset = chartHeight / 2 + recodeMargin; // ヘッ??の表示基準?オフセ??チャート??半???
594
595 // 上段???ー出?
596 if( ( tm % 1440 ) == 0 ) {
597 Date dt = new Date( (startDate + tm) * 60000L );
598 g2.drawString( format1.format( dt ) , posX + recodeMargin , posY2-offset ); // ??,ベ?スラインのx座?y座?
599 offset = 0; // ヘッ??を表示する場合?み上まで線を引く?
600 }
601
602 g2.drawString( getTime2Str(startTime+tm,step,week) , posX + recodeMargin , posY2 ); // ??,ベ?スラインのx座?y座?
603 g2.drawLine( posX, posY1+offset, posX, MAX_Y-chartPadding ); // 始点(x 座?y 座?,終点(x 座?y 座?
604
605 // g2.drawString( getTime2Str(startTime+tm,step) , posX + recodeMargin , posY2 ); // ??,ベ?スラインのx座?y座?
606 // g2.drawLine( posX, posY1-10, posX, MAX_Y-chartPadding-10 ); // 始点(x 座?y 座?,終点(x 座?y 座?
607 posX += (int)(step*timeScale);
608 }
609 }
610
611 // imageHeaderPaintメソ?で使用する 破線?定義
612 private static final Stroke DSAH_STROK = new BasicStroke(
613 1.0f , // BasicStroke の?
614 BasicStroke.CAP_BUTT , // 両端の?
615 BasicStroke.JOIN_MITER , // 輪郭線セグメント?接合部の?
616 1.0f , // 接合トリミングの制限?
617 new float[] {2.0f, 1.0f} , // 破線パターンを表す??
618 0.0f // 破線パターン開始位置のオフセ?
619 );
620
621 /**
622 * 時間スケールに対応したSTEP数を管?るため??クラス
623 *
624 * 時間ヘッ??を表示する場合?ある程度意味のある間隔でラベル表示した?思います?
625 * 全体?描画領域の長さと、時間当たり?スケールファクター?ピクセル数?から?
626 * ラベルの描画間隔を求めます?
627 * 意味のある間隔は、STEPS で定義し?10?30?60?1/4日,1/2日,1日 まで定義して?す?
628 * ?大きな単位以上?場合?、その?単位?整数倍を返します?
629 *
630 * ?間当たり?表示?、MIN_PX として?す?で、この値以下?間隔では描画されません?
631 * 初期値は?00px ?24時間表示できる 600px/24h = 25px にして?す?
632 */
633 private static final class TimeScaleStep {
634 // ? ? ? 1/4 1/2 ?日
635 private static final int[] STEPS = new int[] { 10 , 30 , 60 , 360 , 720 , 1440 };
636 private static final int MIN_PX = 25; // スケールに対する??
637
638 /**
639 * 時間を意味のある?の整数として返します?
640 *
641 * 全体?描画領域の長さと、時間当たり?スケールファクター?ピクセル数?から?
642 * 10?30?60?1/4日,1/2日,1日 までの整数値で返します?
643 * ?大きな単位以上?場合?、その?単位?整数倍を返します?
644 *
645 * @param timeScale 時間(?当たり?ピクセル数
646 * @return 時間スケールに対応した意味のある?の整数
647 */
648 public static final int getStep( final double timeScale ) {
649 int tmStep = (int)Math.ceil(MIN_PX/(timeScale)); // 整数?上げ
650
651 for( int i=0; i<STEPS.length; i++ ) {
652 if( tmStep <= STEPS[i] ) { return STEPS[i]; } // 配?の数字に?上げ
653 }
654
655 // 未設定?場合?、最上位?値の整数倍に?上げ
656 return (int)Math.ceil( tmStep / STEPS[STEPS.length-1] ) * STEPS[STEPS.length-1];
657 }
658 }
659
660 /**
661 * 状況コード?ラベル、色を管?るため??クラス
662 *
663 * 状況に応じたコード?ラベル、色を管?ます?
664 * これは、getColor(状況コー?ラベル) また?、getColor(状況コー?ラベル,色??) で
665 * 要求された??を?部で管?、同じコード?場合に同じ色を返します?
666 * また?凡例作?用に、最も文字数が長?ベルを管?ます?
667 * 色??を指定した?合でも???に要求された状況コードに対応する色を返します?
668 * これは、同?況コードで色違いを作?することができな?とを意味します?
669 * 色??を指定しな??合?、?部の色配?から??番に色を割り当てます?
670 * 色を割り当てる?番は、状況コード?発生?です?よって、検索条件によって?
671 * 状況コード?現れる?が異なると、色も毎回異なることになります?
672 *
673 * 自動割り当ての色は、BLUE,CYAN,GRAY,GREEN,LIGHT_GRAY,MAGENTA,DARK_GRAY,ORANGE,PINK,RED,YELLOW
674 * となっており、それを?ると、RGBをラン?に発生させて色を作?します?
675 * よって、どのような色になるかは全くわかりません?
676 */
677 private static final class ColorMap {
678 private static final Color[] CLR_ARY = new Color[] {
679 Color.BLUE ,Color.CYAN ,Color.GRAY ,Color.GREEN ,Color.LIGHT_GRAY ,Color.MAGENTA ,
680 Color.DARK_GRAY ,Color.ORANGE ,Color.PINK ,Color.RED ,Color.YELLOW
681 };
682 private int lastCnt = 0;
683 private final Map<String,Object[]> colMap = new TreeMap<String,Object[]>();
684 private String maxLabel = "" ; // ?長のラベル
685 private int maxlen = -1 ; // ?長のラベルのlength()
686
687 /**
688 * 状況コードに対応した色オブジェクトを返します?
689 *
690 * 状況コードが初めて?された場合???番に?の色を割り当てます?
691 * また?そ?時?ラベルも管?ます?ラベルと色のセ?は、?例作?時に利用されます?
692 *
693 * 自動割り当ての色は、BLUE,CYAN,GRAY,GREEN,LIGHT_GRAY,MAGENTA,DARK_GRAY,ORANGE,PINK,RED,YELLOW
694 * となっており、それを?ると、RGBをラン?に発生させて色を作?します?
695 * よって、どのような色になるかは全くわかりません?
696 *
697 * @param fgj 状況コー?
698 * @param lbl 状況コード?ラベル
699 * @return 状況コードに対応した色オブジェク?
700 */
701 public Color getColor( final String fgj,final String lbl ) {
702 return getColor( fgj,lbl,null );
703 }
704
705 /**
706 * 状況コードに対応した色オブジェクトを返します?
707 *
708 * 状況コードが初めて?された場合?、引数の色??の色を割り当てます?
709 * また?そ?時?ラベルも管?ます?ラベルと色のセ?は、?例作?時に利用されます?
710 *
711 * 色??を指定した?合でも???に要求された状況コードに対応する色を返します?
712 * これは、同?況コードで色違いを作?することができな?とを意味します?
713 * 色?? ?null の場合?、?動割り当てのメソ?と同じです?
714 * よって、色??の?と、?動割り当てが同時に発生すると、異なる状況コードで
715 * 同じ色が指定される可能性があります?で、混在して使用しな?ください?
716 *
717 * @param fgj 状況コー?
718 * @param lbl 状況コード?ラベル
719 * @param colStr 状況コードに対応した色??(nullの場合?、?動割り当て)
720 * @return 状況コードに対応した色オブジェク?
721 */
722 public Color getColor( final String fgj,final String lbl,final String colStr ) {
723 if( fgj == null ) { return LABEL_COLOR; }
724 if( lbl != null ) {
725 int len = lbl.length();
726 if( len > maxlen ) { maxLabel = lbl; maxlen = len; }
727 }
728
729 Object[] obj = colMap.get( fgj );
730 if( obj == null ) {
731 obj = new Object[2];
732 obj[0] = lbl;
733 obj[1] = (colStr != null) ? StringUtil.getColorInstance( colStr ) : uniqColor();
734
735 colMap.put( fgj,obj );
736 }
737
738 return (Color)obj[1] ;
739 }
740
741 /**
742 * ?のシーケンスに対応した?ユニ?クな色オブジェクトを返します?
743 *
744 * ?カウンターを+?しながら、?部の色オブジェクトを返します?
745 *
746 * 自動割り当ての色は、BLUE,CYAN,GRAY,GREEN,LIGHT_GRAY,MAGENTA,DARK_GRAY,ORANGE,PINK,RED,YELLOW
747 * となっており、それを?ると、RGBをラン?に発生させて色を作?します?
748 * よって、どのような色になるかは全くわかりません?
749 *
750 * @return ユニ?クな色オブジェク?
751 */
752 public Color uniqColor() {
753 Color col = null;
754 if( lastCnt < CLR_ARY.length ) {
755 col = CLR_ARY[lastCnt++];
756 }
757 else {
758 int R=(int)(Math.random()*256);
759 int G=(int)(Math.random()*256);
760 int B=(int)(Math.random()*256);
761 col = new Color(R,G,B);
762 }
763
764 return col;
765 }
766
767 /**
768 * ?で管?て?、ラベル(String)と色オブジェク?Color)の コレクションを返します?
769 *
770 * ?で管?て?コレクションです?
771 * こ?コレクションは、状況コードでソートされて?す?
772 * コレクションの中身は、オブジェクト?列となっており、[0]は、String型?ラベル、[1]は?
773 * Color型?色です?
774 *
775 * @return ラベル(String)と色オブジェク?Color)の コレクション
776 */
777 public Collection<Object[]> values() {
778 return colMap.values();
779 }
780
781 /**
782 * 登録されたラベル??で、最も文字数が長?ベルを返します?
783 *
784 * 凡例で、ラベルの?長を求める?に利用できます?
785 * ただし?簡易的に、length() 計算して??なので、英語?日本語混在??
786 * プロポ?ショナルフォント使用時?厳??長の??ではありません?
787 *
788 * @return ??数が長?ベル
789 */
790 public String getMaxLengthLabel() { return maxLabel; }
791 }
792
793 /**
794 * 時間??を数字に変換します?
795 *
796 * "0800" は?80に?2100" は?260 に変換します?
797 * つまり??位?値に変換します?秒?単位?、?り捨てます?
798 * ここでは、時間文字?が?08:00 の様に?:" を含??合?、削除し?
799 * ?ケタ以上?場合?、前から?ケタ?使?す?
800 * ?ケタ以下(1,2,3ケタ?でも?先?に 0 埋めで、時間文字?にします?
801 * ?ケタ、およ?、null の場合?、defTm 初期値 を返します?
802 *
803 * @param val 時間??の値(0800 など)
804 * @param defTm 引数の時間???null の場合?初期値
805 *
806 * @return 時間??を数字に変換した結果( 80 など)
807 */
808 private int getStr2Time( final String val , final int defTm ) {
809 if( val == null || val.isEmpty() ) { return defTm; }
810
811 // 桁数によって、???仕方が変わるため?
812 int rtnInt = 0;
813 switch( val.length() ) {
814 case 1:
815 case 2: rtnInt = Integer.parseInt( val ); break;
816 case 3: rtnInt = Integer.parseInt( val.substring( 0,1 ) )*60 + Integer.parseInt( val.substring( 1,3 ) ); break;
817 default : rtnInt = Integer.parseInt( val.substring( 0,2 ) )*60 + Integer.parseInt( val.substring( 2,4 ) ); break;
818 }
819
820 return rtnInt ;
821 }
822
823 /**
824 * 日時文字?を数字に変換します?
825 *
826 * 日時文字?は、yyyyMMdd また?、yyyyMMddhhmmss 形式とします?
827 * これを?エポックタイ?ら?経過時間の ?位?値を求めます?
828 * 具体的には、Calendar オブジェクト? getTimeInMillis() の結果を?
829 * 60000 で割り算した?を作?します?
830 * よって、Calendar オブジェクト作?時も、秒?単位??捨てます?
831 * 引数?null の場合?、現在時刻より、作?します?
832 *
833 * @param val 日時文字?の値(yyyyMMdd また?、yyyyMMddhhmmss 形?など)
834 *
835 * @return 日時文字?を?換算した数?
836 */
837 private long getStr2Date( final String val ) {
838 Calendar cal = Calendar.getInstance();
839 str2DateTime = 0;
840 if( val == null ) {
841 cal.set( Calendar.HOUR_OF_DAY, 0 ); // 5.3.5.0 (2011/05/01) 時間の解決規則が適用されるため??時」?は、setメソ?で 0 にセ?する?
842 cal.clear( Calendar.MINUTE );
843 cal.clear( Calendar.SECOND );
844 cal.clear( Calendar.MILLISECOND );
845 }
846 else if( val.length() == 8 ) {
847 cal.clear();
848 cal.set( Integer.parseInt( val.substring( 0,4 ) ) , // 年
849 Integer.parseInt( val.substring( 4,6 ) ) - 1, // ?0から始ま?
850 Integer.parseInt( val.substring( 6,8 ) ) // 日
851 );
852 }
853 else {
854 cal.clear();
855 cal.set( Integer.parseInt( val.substring( 0,4 ) ) , // 年
856 Integer.parseInt( val.substring( 4,6 ) ) - 1, // ?0から始ま?
857 Integer.parseInt( val.substring( 6,8 ) ) , // 日
858 Integer.parseInt( val.substring( 8,10 ) ) , // ?
859 Integer.parseInt( val.substring( 10,12 ) ) // ?
860 );
861 str2DateTime = Integer.parseInt( val.substring( 8,10 ) ) * 60 + Integer.parseInt( val.substring( 10,12 ) ) ;
862 }
863 return (cal.getTimeInMillis() / 60000L); // ?位に変換する?
864 }
865
866 // 5.6.5.0 (2013/06/07) 曜日??タを?列で持っておきます?
867 private static final String[] DAY_OF_WEEK_ja = new String[] { "?,"日","?,"火","水","木","?,"? }; // [0]="? は??? の余計算で?7=0 になる為?
868
869 /**
870 * 数??を時間文字?に変換します?
871 *
872 * 480 は?08" に?260 は?21" に変換します?
873 * 引数の時間は、?を表す整数です??4時間表記であれば? ??1440 の?で収まりますが?
874 * 期間が長??合?、その値を?ます?また??4時間を?る?合?? に戻ります?
875 * ??にする場合??単位???なので?0(?で割り算して、余?、?り捨てます?
876 * step は?0(?単位?表示時に飛?す数です?step=1 なら?60(?単位?step=2 なら?120(?
877 * 単位となります?stepが?24 以下?場合?、そのまま?4時間表記で構いませんが?
878 * それを?ると時間ではなく?日数表記に?替わります?
879 *
880 * @og.rev 5.6.5.0 (2013/06/07) 月単位?場合?、曜日を表示します?
881 *
882 * @param timeVal 引数の時間整数(?
883 * @param step 60?位?ス?プ数( 10,30,60,720,1440 単位となるよ?調整)
884 * @param week カレン?ラスの曜日フィール?DAY_OF_WEEK)
885 *
886 * @return 数字を時間??に変換した結果( "08" など)
887 */
888 // private String getTime2Str( final int timeVal, final int step ) {
889 private String getTime2Str( final int timeVal, final int step, final int week ) {
890
891 int dtm = (timeVal / 60 / 24 ); // 日
892 int htm = ((timeVal / 60) % 24 ); // ??4時間制)
893 int mtm = (timeVal % 60 ); // ??0?制)
894
895 StringBuilder rtn = new StringBuilder();
896
897 if( step >= 1440 ) {
898 // rtn.append( dtm ).append( "d" ); // 5.6.5.0 (2013/06/07) 相対日付?
899 rtn.append( DAY_OF_WEEK_ja[ ( dtm + week ) % 7 ] ); // 曜日を表示
900 }
901 else {
902 if( htm < 10 ) { rtn.append( "0" ); }
903 rtn.append( htm );
904
905 if( step < 60 ) {
906 rtn.append( ":" );
907 if( mtm < 10 ) { rtn.append( "0" ); }
908 rtn.append( mtm );
909 }
910 }
911
912 return rtn.toString();
913 }
914
915 // 引数に?を追?る?
916
917 /**
918 * 表示?の編?並び替?が可能かど?を返しま?
919 *
920 * @return 表示?の編?並び替?が可能かど?(false:不可能)
921 */
922 @Override
923 public boolean isEditable() {
924 return false;
925 }
926 }