/**** ファイル名 : BTinyEditor.h ****/
#ifndef BTINYEDITORAPP #define BTINYEDITORAPP //--------------------------------------------------------------------- #include <Be.h> #include "MainWindow.h" //--------------------------------------------------------------------- #define APPLICATION_SIGNATURE "application/x-vnd.vow-betinyeditor" //--------------------------------------------------------------------- class BTinyEditorApp : public BApplication { private: BFilePanel *open_filepanel; public: BTinyEditorApp(); ~BTinyEditorApp(); void MessageReceived(BMessage *msg); void RefsReceived(BMessage *message); }; //--------------------------------------------------------------------- #endif
/**** ファイル名 : BTinyEditor.cpp ****/
//--------------------------------------------------------------------- #include "BTinyEditor.h" #include <Be.h> //--------------------------------------------------------------------- BTinyEditorApp::BTinyEditorApp() :BApplication(APPLICATION_SIGNATURE) { BEditorWindow *mainwnd=new BEditorWindow( BRect(MAINWINDOW_POSITION_LEFT,MAINWINDOW_POSITION_TOP, MAINWINDOW_POSITION_WIDTH+MAINWINDOW_POSITION_LEFT-1, MAINWINDOW_POSITION_HEIGHT+MAINWINDOW_POSITION_TOP-1), MAINWINDOW_TITLE); open_filepanel= new BFilePanel(); mainwnd->Show(); } //--------------------------------------------------------------------- BTinyEditorApp::~BTinyEditorApp() { delete open_filepanel; } //--------------------------------------------------------------------- void BTinyEditorApp::MessageReceived(BMessage *msg) { switch(msg->what) { case MSG_OPEN: open_filepanel->Show(); break; default: BApplication::MessageReceived(msg); } } //--------------------------------------------------------------------- void BTinyEditorApp::RefsReceived(BMessage *message) { type_code ref_type; int32 ref_count; entry_ref ref; BEntry entry; message->GetInfo("refs", &ref_type,&ref_count); for (int i=0;i<ref_count;i++) { message->FindRef("refs",i,&ref); if(entry.SetTo(&ref)==B_OK) { WindowAt(0)->Lock(); ((BEditorWindow *)WindowAt(0))->OpenFile(&entry); WindowAt(0)->Unlock(); return; } } } //---------------------------------------------------------------------
/**** ファイル名 : BTinyEditor.h ****/
#ifndef BTINYEDITORAPP #define BTINYEDITORAPP //--------------------------------------------------------------------- #include <Be.h> #include "MainWindow.h" //--------------------------------------------------------------------- #define APPLICATION_SIGNATURE "application/x-vnd.vow-betinyeditor" //--------------------------------------------------------------------- class BTinyEditorApp : public BApplication { private: BList *EditorList; BFilePanel *open_filepanel; public: BTinyEditorApp(); ~BTinyEditorApp(); BEditorWindow *AddEditor(void); void MessageReceived(BMessage *msg); void RefsReceived(BMessage *message); }; //--------------------------------------------------------------------- #endif
/**** ファイル名 : BTinyEditor.cpp ****/
//--------------------------------------------------------------------- #include "BTinyEditor.h" #include <Be.h> //--------------------------------------------------------------------- BTinyEditorApp::BTinyEditorApp() :BApplication(APPLICATION_SIGNATURE) { EditorList=new BList(); open_filepanel= new BFilePanel(); AddEditor(); } //--------------------------------------------------------------------- BTinyEditorApp::~BTinyEditorApp() { delete open_filepanel; for(int i=EditorList->CountItems()-1;i>=0;i--) { BEditorWindow *targetwnd= ((BEditorWindow *)EditorList->ItemAt(i)); targetwnd->Quit(); EditorList->RemoveItem(targetwnd); } delete EditorList; } //--------------------------------------------------------------------- BEditorWindow *BTinyEditorApp::AddEditor(void) { BEditorWindow *mainwnd=new BEditorWindow( BRect(MAINWINDOW_POSITION_LEFT,MAINWINDOW_POSITION_TOP, MAINWINDOW_POSITION_WIDTH+MAINWINDOW_POSITION_LEFT-1, MAINWINDOW_POSITION_HEIGHT+MAINWINDOW_POSITION_TOP-1), MAINWINDOW_TITLE); EditorList->AddItem((void *)mainwnd); mainwnd->Show(); return mainwnd; } //--------------------------------------------------------------------- void BTinyEditorApp::MessageReceived(BMessage *msg) { switch(msg->what) { case MSG_OPEN: open_filepanel->Show(); break; default: BApplication::MessageReceived(msg); } } //--------------------------------------------------------------------- void BTinyEditorApp::RefsReceived(BMessage *message) { type_code ref_type; int32 ref_count; entry_ref ref; BEntry entry; message->GetInfo("refs", &ref_type,&ref_count); for (int i=0;i<ref_count;i++) { message->FindRef("refs",i,&ref); if(entry.SetTo(&ref)==B_OK) { ((BEditorWindow *)EditorList->ItemAt(0))->Lock(); ((BEditorWindow *)EditorList->ItemAt(0))->OpenFile(&entry); ((BEditorWindow *)EditorList->ItemAt(0))->Unlock(); return; } } } //---------------------------------------------------------------------
発行元クラス | 処理クラス | メッセージ | 処理 |
---|---|---|---|
BEditorWindow | BTinyEditorApp | MSG_OPEN | オープン用のファイルパネルを開く。 |
- | BTinyEditorApp | B_REFS_RECEIVED | ウィンドウを追加。メッセージからオープンするファイル情報を取得し、追加したウィンドウのOpenFile関数を呼び出す。 |
BEditorWindow | BTinyEditorApp | MSG_ADDEDITOR | ウィンドウを追加する。 |
BEditorWindow | BEditorWindow | MSG_SAVE | ファイル名が設定されているかを調べ、設定されていればファイルを上書き保存する。設定されていなければ、MSG_SAVEASの処理を行う。 |
BEditorWindow | BEditorWindow | MSG_SAVEAS | 保存用のファイルパネルを開く。 |
- | BEditorWindow | B_SAVE_REQUESTED | メッセージから保存先のファイル情報を取得し、SaveFile関数を呼び出す。 |
- | BEditorWindow | B_QUIT_REQUESTED |
ファイルが保存済みかを確認。保存済みでなければ、保存確認メッセージを表示し、必要に応じてMSG_SAVEメッセージを発行。 ファイルが保存済みであるか、保存確認メッセージで「Don't Save」を選択した場合は、ウィンドウの終了を許可し、BTinyEditorAppクラスにMSG_CLOSEDメッセージを発行する。MSG_CLOSEDメッセージには自分自身のポインタを付加しておく。 |
BEditorWindow | BTinyEditorApp | MSG_CLOSED |
メッセージから終了したウィンドウを取得し、リストからそのウィンドウを削除する。 リストの登録数が0になったら、自分自身にB_QUIT_REQUESTEDメッセージを発行する。 |
- | BTinyEditorApp | B_QUIT_REQUESTED | 作成したクラスの実体を削除し、アプリケーションを終了する。 |
BEditorWindow | BTinyEditorApp | MSG_QUIT | 開いているすべてのウィンドウにB_QUIT_REQUESTEDメッセージを発行する。 |
/**** ファイル名 : BTinyEditor.cpp ****/
//--------------------------------------------------------------------- void BTinyEditorApp::MessageReceived(BMessage *msg) { switch(msg->what) { case MSG_OPEN: open_filepanel->Show(); break; case MSG_QUIT: for(int i=EditorList->CountItems()-1;i>=0;i--) ((BEditorWindow *)EditorList->ItemAt(i))-> PostMessage(B_QUIT_REQUESTED); break; case MSG_CLOSED: { BEditorWindow *targetwnd; msg->FindPointer("wnd",(void **)&targetwnd); if(targetwnd!=NULL) { targetwnd->Quit(); EditorList->RemoveItem(targetwnd); if(EditorList->CountItems()==0) PostMessage(B_QUIT_REQUESTED); } } break; case MSG_ADDEDITOR: AddEditor(); break; default: BApplication::MessageReceived(msg); } } //--------------------------------------------------------------------- void BTinyEditorApp::RefsReceived(BMessage *message) { type_code ref_type; int32 ref_count; entry_ref ref; BEntry entry; message->GetInfo("refs", &ref_type,&ref_count); for(int i=0;i<ref_count;i++) { message->FindRef("refs",i,&ref); if(entry.SetTo(&ref)==B_OK) { if(entry.IsFile()) { BEditorWindow *targetwnd; targetwnd=AddEditor(); targetwnd->Lock(); targetwnd->OpenFile(&entry); targetwnd->Unlock(); } } } } //--------------------------------------------------------------------- void BTinyEditorApp::ReadyToRun() { if(EditorList->CountItems()==0) AddEditor(); } //---------------------------------------------------------------------
の追加と、BEditorWindowクラスの定義に#define MSG_CLOSED 'mcld' #define MSG_QUIT 'mqit' #define MSG_ADDEDITOR 'madd'
editingpathが追加されています。editingpathは、編集中のファイルのパスを保存するために使用します。save_to_quitについては、後で説明します。class BEditorWindow : public BWindow { private: BFilePanel *save_filepanel; bool save_to_quit; void SetFileName(BEntry *entry); public: BPath *editingpath; BEditorView *mainview; //-----------------------------------------------------------------
MSG_ADDEDITORメッセージを発行する「New Text」が追加されています。メッセージの送信先はbe_app、つまりBTinyEditorAppクラスになっています。BMenu *filemenu=new BMenu("File"); filemenu->AddItem(new BMenuItem("Open...",new BMessage(MSG_OPEN))); filemenu->ItemAt(0)->SetTarget(be_app); filemenu->AddItem(new BMenuItem("New Text",new BMessage(MSG_ADDEDITOR))); filemenu->ItemAt(1)->SetTarget(be_app); filemenu->AddItem(new BMenuItem("Save",new BMessage(MSG_SAVE))); filemenu->ItemAt(2)->Message()->AddBool("to_quit",false); filemenu->AddItem(new BMenuItem("Save As...",new BMessage(MSG_SAVEAS))); filemenu->ItemAt(3)->Message()->AddBool("to_quit",false); filemenu->AddSeparatorItem(); filemenu->AddItem(new BMenuItem("Close",new BMessage(B_QUIT_REQUESTED))); filemenu->AddSeparatorItem(); filemenu->AddItem(new BMenuItem("Quit",new BMessage(MSG_QUIT))); filemenu->ItemAt(7)->SetTarget(be_app); mainmenu->AddItem(filemenu);
/**** ファイル名 : BMemoView.h ****/
#ifndef BMEMOVIEW #define BMEMOVIEW //--------------------------------------------------------------------- #include <Be.h> //--------------------------------------------------------------------- class BMemoView : public BTextView { public: bool Modified; BMemoView(BRect frame,const char *name,uint32 resizingMode); void MessageReceived(BMessage *msg); void KeyDown(const char *bytes,int32 numBytes); }; //--------------------------------------------------------------------- #endif
/**** ファイル名 : BMemoView.cpp ****/
//--------------------------------------------------------------------- #include "BMemoView.h" //--------------------------------------------------------------------- BMemoView::BMemoView(BRect frame,const char *name,uint32 resizingMode) :BTextView(frame,name,BRect(0,0,frame.Width(),frame.Height()), resizingMode,B_WILL_DRAW) { Modified=false; } //--------------------------------------------------------------------- void BMemoView::MessageReceived(BMessage *msg) { switch(msg->what) { case B_UNDO: case B_COPY: case B_CUT: case B_PASTE: Modified=true; default: BTextView::MessageReceived(msg); } } //--------------------------------------------------------------------- void BMemoView::KeyDown(const char *bytes,int32 numBytes) { switch(*bytes) { case B_LEFT_ARROW: case B_RIGHT_ARROW: case B_UP_ARROW: case B_DOWN_ARROW: case B_INSERT: case B_HOME: case B_END: case B_PAGE_UP: case B_PAGE_DOWN: case B_FUNCTION_KEY: break; default: Modified=true; } BTextView::KeyDown(bytes,numBytes); } //---------------------------------------------------------------------
BMemoViewクラスのModified変数を調べ、trueならば、BAlertクラスで保存するか否かを確認します。「Cancel」が選択された場合は、falseを返して関数を終了します。QuitRequested関数の戻り値としてfalseを設定すると、ウィンドウの終了処理が中断されます。//--------------------------------------------------------------------- bool BEditorWindow::QuitRequested() { BMemoView *memo; bool result; memo=((BMemoView *)FindView("memo")); result=false; if(memo!=NULL) { if(memo->Modified) { char m[1024]; int32 idx; BAlert *wrnmsg; sprintf(m,"Save changes to the document \"%s\"?", (editingpath!=NULL)?editingpath->Leaf():"Untitled"); wrnmsg=new BAlert("Warning!!", m, "Cancel","Don't save","Save", B_WIDTH_AS_USUAL,B_OFFSET_SPACING, B_WARNING_ALERT); wrnmsg->SetShortcut(0,B_ESCAPE); idx=wrnmsg->Go(); if(idx==0) return false; if(idx==2) { BMessage *msg=new BMessage(MSG_SAVE); msg->AddBool("to_quit",true); PostMessage(msg); return false; } } } BMessage *msg_closed=new BMessage(MSG_CLOSED); msg_closed->AddPointer("wnd",this); be_app->PostMessage(msg_closed); return true; }; //---------------------------------------------------------------------
SaveFile関数では、保存が正常に終了した場合、save_to_quitの値を調べて、trueならばB_QUIT_REQUESTEDメッセージを発行します。//--------------------------------------------------------------------- void BEditorWindow::MessageReceived(BMessage *msg) { switch(msg->what) { case B_UNDO: case B_COPY: case B_CUT: case B_PASTE: case B_SELECT_ALL: ((BMemoView *)FindView("memo"))->MessageReceived(msg); break; case MSG_SAVE: msg->FindBool("to_quit",&save_to_quit); if(editingpath!=NULL) { BEntry entry; entry.SetTo(editingpath->Path()); SaveFile(&entry); break; } case MSG_SAVEAS: msg->FindBool("to_quit",&save_to_quit); save_filepanel->SetTarget(this); save_filepanel->Show(); break; case B_SAVE_REQUESTED: { entry_ref ref; BString nam; BDirectory dir; BEntry entry; msg->FindRef("directory",&ref); msg->FindString("name",&nam); dir.SetTo(&ref); if(entry.SetTo(&dir,nam.String())==B_OK) { SaveFile(&entry); return; } } break; default: BWindow::MessageReceived(msg); } } //--------------------------------------------------------------------- void BEditorWindow::SaveFile(BEntry *entry) { BFile fil; off_t wsize; off_t tsize; try { fil.SetTo(entry,B_READ_WRITE | B_CREATE_FILE); tsize=strlen(((BTextView *)FindView("memo"))->Text()); wsize=fil.WriteAt(0,((BTextView *)FindView("memo"))->Text(), tsize); if(tsize==wsize) { SetFileName(entry); if(save_to_quit) PostMessage(new BMessage(B_QUIT_REQUESTED)); } } catch(...) { BAlert *altmsg = new BAlert("Error", "File write failed!!","OK", NULL,NULL,B_WIDTH_AS_USUAL, B_WARNING_ALERT); altmsg->Go(); } } //---------------------------------------------------------------------
//--------------------------------------------------------------------- void BEditorWindow::SetFileName(BEntry *entry) { if(editingpath==NULL) editingpath=new BPath(); entry->GetPath(editingpath); if(editingpath!=NULL) { char nam[B_FILE_NAME_LENGTH]; entry->GetName(nam); SetTitle(nam); } ((BMemoView *)FindView("memo"))->Modified=false; } //---------------------------------------------------------------------
圧縮ファイル R5 Intel環境で確認 |
BTinyEditor20000530.zip |
ソースファイル | BTinyEditor.cpp |
BTinyEditor.h | |
BMemoView.cpp | |
BMemoView.h | |
main.cpp | |
MainWindow.cpp | |
MainWindow.h |