b. パーツFileXYの修正
1.WorkFrame IDEアイコンをクリックし、「既存のオブジェクトを
オープンします」をクリックする。
DataColl.IWPをダブルクリックする。
2.WorkFrameのDataCol.vbbをダブルクリックして、ビジュアル・ビルダーを開く。
3.非ビジュアル・パーツのFileXYをダブルクリックする。
4.クラス・エディターの必要なインクルード・ファイルに、"Comment.hpp" _COMMENT_
を追加する。
5.パーツ・インターフェース・エディターに下記の項目を追加する。
FileXYパーツの追加 | |||
属性 |
タイプ |
コメント |
優先 |
commentItems |
IVSequence<Comment*>* |
コメントをシーケンシャルに収納する |
O |
set関数の引数のconstを削除 |
|||
addComment |
IString |
指定したフォーマットでコメントを書く場合は、文字列yesを代入する |
O |
イベント |
コメント |
優先 |
|
exportToFileAddComment |
セーブするコメントのフォーマットを指定していることを通知する |
O |
|
importFromFileAddComment |
指定したフォーマットのコメントが有ることを通知する |
O |
6.「ファイル」->「保管および生成」->「フィーチャー・ソース」をクリックする。
7.「FileXY−フィーチャー・ソース・コードを作成します」ダイアログにおいて、
メンバー関数の
virtual IString addComment() const
virtual IVSequence<Comment*>* commentItems() const
virtual FileXY& setAddComment( const IString& aAddComment )
virtual FileXY& setCommentItems( IVSequence<Comment*>* aCommentItems )
属性データ・メンバーの
iAddComment
iCommentItems
イベント・データ・メンバー
addCommentId
commentItemsId
exportToFileAddCommentId
importFromFileAddCommentId
をCtrlキーを押しながらクリックして、選択する。
8.「選択したものの生成」をクリックして、FileXY.cpvとFileXY.hpvに
上記の項目を追加する。
9.FileXY.hpvに以下が自動的に追加される。
// Feature source code generation begins here...
public:
virtual IVSequence<Comment*>* commentItems() const;
virtual FileXY& setCommentItems(IVSequence<Comment*>* aCommentItems);
virtual IString addComment() const;
virtual FileXY& setAddComment(const IString& aAddComment);
static const INotificationId IVB_IMPORT commentItemsId;
static const INotificationId IVB_IMPORT exportToFileAddCommentId;
static const INotificationId IVB_IMPORT importFromFileAddCommentId;
static const INotificationId IVB_IMPORT addCommentId;
private:
IVSequence<Comment*>* iCommentItems;
IString iAddComment;
// Feature source code generation ends here.
10.FileXY.hpvに以下のコードを入力する。
// User's source code generation begins here...
protected:
IString iCommentImported;
virtual void userConstructor();
// User's source code generation ends here.
11.セーブする。
12.FileXY.cpvを下記のように修正する。
long FileXY::exportToFile(const IString& filename)
{
ofstream ofStream;
DataXY* iExportItem;
long iCount=0;
IVSequence<DataXY*>::Cursor SeqCursor( *iItems );
IVSequence<Comment*>::Cursor CommentCursor( *iCommentItems ); // 変更箇所
Comment* iComment; // 変更箇所
// 変更開始箇所
if( iAddComment=="yes" ) // 指定されたフォーマットでコメントを記入する場合
{
notifyObservers(INotificationEvent(FileXY::exportToFileAddCommentId, *this));
ofStream.open( filename, ios::app ); // 既存のデータに継ぎ足す
}
else
{
if( iCommentImported=="yes" ) // 他のフォーマットでコメントが記入されている場合
{
ofStream.open( filename );
CommentCursor.setToFirst(); // コメントの最初の項にセット
while( CommentCursor.isValid() ) // コメントが存在する間、繰り返す
{
// コメントのカーソル位置のテキストをiCommentに代入する
iComment = iCommentItems->elementAt( CommentCursor );
// クラスCommentのtextをファイルにセーブする
ofStream << iComment->text() << endl;
CommentCursor.setToNext(); // 次の項に移る
}
}
else // コメントがない場合
{
ofStream.open( filename ); // ファイルのオープン
}
}
// 変更箇所終了
if( !ofStream ) // 例外処理
{
IString errorText = IString( "ファイル" ) + filename + "をオープンできません。";
IException exc( errorText, 0, IException::unrecoverable );
ITHROW( exc );
} // 例外処理終了
if( iType=="comma" ) // データ間をコンマで区切る場合
{
for( SeqCursor.setToFirst(); SeqCursor.isValid(); SeqCursor.setToNext() )
{
iExportItem = iItems->elementAt( SeqCursor );
ofStream << iExportItem->dataX() << "," << iExportItem->dataY() << endl;
iCount++;
}
}
if( iType=="space" ) // データ間をスペースで区切る場合
{
for( SeqCursor.setToFirst(); SeqCursor.isValid(); SeqCursor.setToNext() )
{
iExportItem = iItems->elementAt( SeqCursor );
ofStream << iExportItem->dataX() << " " << iExportItem->dataY() << endl;
iCount++;
}
}
ofStream.close(); // ファイルのクローズ
return iCount;
}
long FileXY::importFromFile(const IString& filename)
{
ifstream ifStream;
DataXY* iImportItem;
Comment* iCommentItem; // 変更箇所
long iCount=0;
double iDataX;
double iDataY;
char iCharacter;
IString iText;
long iMark; // 変更箇所
ifStream.open( filename ); // ファイルのオープン
if( !ifStream ) // 例外処理
{
IString errorText = IString( "ファイル" ) + filename + "をオープンできません。";
IException exc( errorText, 0, IException::unrecoverable );
ITHROW( exc );
} // 例外処理終了
// 変更開始箇所
if( ifStream.get()=='%' ) // 頭文字が'%'の場合
{
ifStream.close(); // コメントが有るため、一旦ファイルを閉じる
// コメントが有ることを知らせる
notifyObservers(INotificationEvent(FileXY::importFromFileAddCommentId, *this));
// コメントがインポートされたことを示す
iCommentImported = IString( "yes" );
}
else
{
ifStream.close(); // 一旦ファイルを閉じる
// コメントがないことを示す
iCommentImported = IString( "no" );
}
// コメントの処理を終えて、データを入力するために再びファイルを開く
ifStream.open( filename ); // ファイルのオープン
if( !ifStream ) // 例外処理
{
IString errorText = IString( "ファイル" ) + filename + "をオープンできません。";
IException exc( errorText, 0, IException::unrecoverable );
ITHROW( exc );
} // 例外処理終了
// commentItemsのイベント通知機能を禁止
iCommentItems->disableNotification();
iMark = ifStream.tellg(); // ifStreamの最初の行番号を代入する
iText = IString::lineFrom( ifStream ); // 最初の行のテキストを代入する
// 文字列の最初の文字を取り出し、"%"と比較する
while( iText.subString(1,1) =="%" )
{
// クラスCommentのiCommentItemの実体(オブジェクト)を作成
iCommentItem = new Comment;
// iCommentItemにiTextを代入する
iCommentItem->setText( iText );
iCommentItems->addAsLast( iCommentItem ); // コメントに追加する
iMark = ifStream.tellg(); // ifStreamの現在の行番号を代入する
iText = IString::lineFrom( ifStream ); // 現在の行のテキストを代入する
}
// commentItemsのイベント通知機能を開始
iCommentItems->enableNotification();
// commentItemsのイベントを通知する。
notifyObservers(INotificationEvent(FileXY::commentItemsId, *this));
ifStream.seekg( iMark ); // データが書き込まれている行に移す
// 変更箇所終了
// itemsのイベント通知機能を禁止
iItems->disableNotification();
if( iType=="comma" ) // データ間をコンマで区切る場合
{
// 最後のデータまで繰り返す。
while( !ifStream.eof() )
{
// DataXY型のiImportItemの実体(オブジェクト)を生成
iImportItem = new DataXY;
// ファイルからデータをdataX、コンマ、dataYの順に取り出す。
ifStream >> iDataX >> iCharacter >> iDataY;
// iImportItemにdataXとdataYを代入する。
iImportItem->setDataX( iDataX );
iImportItem->setDataY( iDataY );
// iItemsの最後に加える。
iItems->addAsLast( iImportItem );
iCount++;
}
}
if( iType=="space" ) // データ間をスペースで区切る場合
{
// 最後のデータまで繰り返す。
while( !ifStream.fail() ) // ifStream.eof()と同じ
{
// DataXY型のiImportItemの実体(オブジェクト)を生成
iImportItem = new DataXY;
// ファイルからデータをdataX、dataYの順に取り出す。
ifStream >> iDataX >> iDataY;
// iImportItemにdataXとdataYを代入する。
iImportItem->setDataX( iDataX );
iImportItem->setDataY( iDataY );
// iItemsの最後に加える。
iItems->addAsLast( iImportItem );
iCount++;
}
}
// itemsの最後のオブジェクトのポインターを取得する。
// このままでは、最後のデータが2回入るため。
iImportItem = iItems->lastElement();
// オブジェクトのポインターを削除する。
iItems->removeLast();
// オブジェクトを削除する。
delete iImportItem;
iCount -=1;
ifStream.close(); // ファイルのクローズ
// itemsのイベント通知機能を開始
iItems->enableNotification();
// itemsのイベントを通知する。
notifyObservers(INotificationEvent(FileXY::itemsId, *this));
return iCount;
}
long FileXY::save()
{
return exportToFile( iItemsFilename ); // exportToFileを実行する。
}
long FileXY::saveAs(const IString& filename)
{
long iCount;
setItemsFilename( filename ); // 変更したファイル名を記憶する。// 変更箇所
iCount = exportToFile( filename ); // ファイルへ保存
return iCount;
}
long FileXY::open(const IString& filename)
{
long iCount;
newFile(); // 既存のデータをすべて削除する。
setItemsFilename( filename ); // 開いたファイル名を記憶する。// 変更箇所
iCount = importFromFile( filename ); // ファイルから読み込む。
return iCount;
}
void FileXY::newFile()
{
// itemsの全ての項目がなくなるまで繰り返す。
while( !iItems->isEmpty() )
{
// itemsの最初のオブジェクトのポインターを取得する。
DataXY* iImportItem = iItems->firstElement();
// オブジェクトのポインターを削除する。
iItems->removeFirst();
// オブジェクトを削除する。
delete iImportItem;
}
// 変更開始箇所
// commentItemsの全ての項目を削除する。
if( !iCommentItems->isEmpty() )
{
// commentItemsの最初のオブジェクトのポインターを取得する。
Comment* iCommentItem = iCommentItems->firstElement();
// オブジェクトのポインターを削除する。
iCommentItems->removeFirst();
// オブジェクトを削除する。
delete iCommentItem;
}
// 変更箇所終了
return;
}
// Feature source code generation ends here.
// 変更開始箇所
// User's source code generation begins here...
void FileXY::userConstructor()
{
IVSequence<Comment*>* initialItems;
// commentItemsにアクセスできるように、IVSequence<Comment*>型のオブジェクトを生成
// IVSequence<Comment*>型のinitialItemsのオブジェクトを生成
initialItems = new IVSequence<Comment*>;
// CommenttemsにinitialItemsを代入
setCommentItems( initialItems );
iCommentImported = IString( "no" ); // 初期化
}
// User's source code generation ends here.
// 変更箇所終了
13.セーブする。
14.FileXY−クラス・エディターのユーザー・コンストラクター・コードに
userConstructor();
と入力する。
このパーツが呼び出されたとき、まずuserConstructor()を処理する。
注意:必ず、userConstructor()の後に、; を書くこと、
15.「ファイル」->「保管」をクリックする。
16.今後パーツFileXYを利用できるように、覚え書きFileXY.htmlを
下記のように修正する。
パーツFileXYの説明
2次元(x, y)データをセーブおよびロードするためのパーツである。
FileXYパーツ | |||
属性 |
タイプ |
コメント |
優先 |
itemsFilename |
IString |
ファイル名の設定 |
O |
type |
IString |
データ間の区切り方 commentまたはspace |
O |
items |
IVSequence<DataXY*>* |
全データをシーケンシャルに収納する |
O |
set関数の引数のconstを削除 |
|||
commentItems |
IVSequence<Comment*>* |
コメントをシーケンシャルに収納する |
O |
set関数の引数のconstを削除 |
|||
addComment |
IString |
指定したフォーマットでコメントを書く場合は、文字列yesを代入する |
O |
イベント |
|
|
|
exportToFileAddComment |
セーブするコメントのフォーマットを指定していることを通知する |
O |
|
importFromFIleAddComment |
指定したフォーマットのコメントが有ることを通知する |
O |
|
アクション |
タイプ |
パラメータ |
|
exportToFile |
long |
const IString& filename |
|
importFromFile |
long |
const IString& filename |
|
save |
long |
|
O |
saveAs |
long |
const IString& filename |
O |
open |
long |
const IString& filename |
O |
newFile |
void |
|
O |
データのセーブの仕方
1.データ間をコンマで区切る場合は、属性typeを文字列commaにする。例:1.3,6.54
2.データ間をスペースで区切る場合は、属性typeを文字列spaceにする。例:1.3 6.54
ファイルを開くにはopen( filename )、データの上書保存にはsave ()、データの別名保存は
saveAs( filename )を用いる。
指定したフォーマットでコメントを記入する場合は、属性addCommentに文字列yesを
代入する。
ファイルに書き込む場合は、イベントexportToFileAddCommentとコメントを書き込む
パーツのアクションexportToFileとを接続する。
ファイルから読み込む場合は、イベントimportFromFileAddCommentとコメントを読み込む
パーツのアクションimportFromFileとを接続する。
必要なファイル |
||
DataColl.vbb |
FileXY.cpv |
FileXY.hpv |
|
DataXY.cpv |
DataXY.hpv |
|
Comment.cpv |
Comment.hpv |