diff --git a/src/apps/resedit/ResView.cpp b/src/apps/resedit/ResView.cpp index 67f240db06..21ea79967c 100644 --- a/src/apps/resedit/ResView.cpp +++ b/src/apps/resedit/ResView.cpp @@ -9,9 +9,10 @@ #include #include -#include #include #include +#include +#include #include #include @@ -35,7 +36,6 @@ enum { M_NEW_FILE = 'nwfl', M_OPEN_FILE, M_SAVE_FILE, - M_SAVE_FILE_AS, M_QUIT, M_SELECT_FILE, M_DELETE_RESOURCE, @@ -45,7 +45,10 @@ enum { ResView::ResView(const BRect &frame, const char *name, const int32 &resize, const int32 &flags, const entry_ref *ref) : BView(frame, name, resize, flags), - fIsDirty(false) + fRef(NULL), + fSaveStatus(FILE_INIT), + fOpenPanel(NULL), + fSavePanel(NULL) { SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); if (ref) { @@ -53,7 +56,6 @@ ResView::ResView(const BRect &frame, const char *name, const int32 &resize, *fRef = *ref; fFileName = fRef->name; } else { - fRef = NULL; fFileName = "Untitled "; fFileName << sUntitled; sUntitled++; @@ -88,9 +90,11 @@ ResView::ResView(const BRect &frame, const char *name, const int32 &resize, width = be_plain_font->StringWidth("1000 bytes") + 20; fListView->AddColumn(new BSizeColumn("Size", width, 10, 100), 4); - fFilePanel = new BFilePanel(B_OPEN_PANEL); + fOpenPanel = new BFilePanel(B_OPEN_PANEL); if (ref) OpenFile(*ref); + + fSavePanel = new BFilePanel(B_SAVE_PANEL); } @@ -98,17 +102,27 @@ ResView::~ResView(void) { EmptyDataList(); delete fRef; - delete fFilePanel; + delete fOpenPanel; + delete fSavePanel; } void ResView::AttachedToWindow(void) { - for(int32 i = 0; i < fBar->CountItems(); i++) + for (int32 i = 0; i < fBar->CountItems(); i++) fBar->SubmenuAt(i)->SetTargetForItems(this); fListView->SetTarget(this); - fFilePanel->SetTarget(BMessenger(this)); + + BMessenger messenger(this); + fOpenPanel->SetTarget(messenger); + fSavePanel->SetTarget(messenger); + + Window()->Lock(); + BString title("ResEdit: "); + title << fFileName; + Window()->SetTitle(title.String()); + Window()->Unlock(); } @@ -128,6 +142,32 @@ ResView::MessageReceived(BMessage *msg) be_app->PostMessage(M_SHOW_OPEN_PANEL); break; } + case B_CANCEL: { + if (fSaveStatus == FILE_QUIT_AFTER_SAVE) + SetSaveStatus(FILE_DIRTY); + break; + } + case B_SAVE_REQUESTED: { + entry_ref saveDir; + BString name; + if (msg->FindRef("directory",&saveDir) == B_OK && + msg->FindString("name",&name) == B_OK) { + SetTo(saveDir,name); + SaveFile(); + } + break; + } + case M_SAVE_FILE: { + if (!fRef) + fSavePanel->Show(); + else + SaveFile(); + break; + } + case M_SHOW_SAVE_PANEL: { + fSavePanel->Show(); + break; + } case M_QUIT: { be_app->PostMessage(B_QUIT_REQUESTED); break; @@ -140,7 +180,7 @@ ResView::MessageReceived(BMessage *msg) break; } case M_SELECT_FILE: { - fFilePanel->Show(); + fOpenPanel->Show(); break; } case M_DELETE_RESOURCE: { @@ -175,6 +215,27 @@ ResView::MessageReceived(BMessage *msg) } +status_t +ResView::SetTo(const entry_ref &dir, const BString &name) +{ + entry_ref fileRef; + + BPath path(&dir); + path.Append(name.String()); + BFile file(path.Path(), B_CREATE_FILE | B_READ_WRITE); + if (file.InitCheck() != B_OK) + return B_ERROR; + + if (!fRef) + fRef = new entry_ref(); + + BEntry entry(path.Path()); + entry.GetRef(fRef); + fFileName = name; + return B_OK; +} + + void ResView::OpenFile(const entry_ref &ref) { @@ -217,6 +278,44 @@ ResView::OpenFile(const entry_ref &ref) } +void +ResView::SaveFile(void) +{ + if (fSaveStatus == FILE_CLEAN || !fRef) + return; + + BFile file(fRef,B_READ_WRITE); + BResources res(&file,true); + file.Unset(); + + for (int32 i = 0; i < fListView->CountRows(); i++) { + ResDataRow *row = (ResDataRow*)fListView->RowAt(i); + ResourceData *data = row->GetData(); + res.AddResource(data->GetType(), data->GetID(), data->GetData(), + data->GetLength(), data->GetName()); + } + + res.Sync(); + + if (fSaveStatus == FILE_QUIT_AFTER_SAVE && Window()) + Window()->PostMessage(B_QUIT_REQUESTED); + SetSaveStatus(FILE_CLEAN); +} + + +void +ResView::SaveAndQuit(void) +{ + SetSaveStatus(FILE_QUIT_AFTER_SAVE); + if (!fRef) { + fSavePanel->Show(); + return; + } + + SaveFile(); +} + + void ResView::BuildMenus(BMenuBar *menuBar) { @@ -224,14 +323,15 @@ ResView::BuildMenus(BMenuBar *menuBar) menu->AddItem(new BMenuItem("New" B_UTF8_ELLIPSIS, new BMessage(M_NEW_FILE), 'N')); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS, new BMessage(M_OPEN_FILE), 'O')); + menu->AddSeparatorItem(); + menu->AddItem(new BMenuItem("Save", new BMessage(M_SAVE_FILE), 'S')); + menu->AddItem(new BMenuItem("Save As" B_UTF8_ELLIPSIS, new BMessage(M_SHOW_SAVE_PANEL), 'S', + B_COMMAND_KEY | B_SHIFT_KEY)); menuBar->AddItem(menu); menu = new BMenu("Resource"); - menu->AddItem(new BMenuItem("Add" B_UTF8_ELLIPSIS, new BMessage(M_SELECT_FILE), 'F')); menu->AddItem(new BMenuItem("Delete", new BMessage(M_DELETE_RESOURCE), 'D')); - - menuBar->AddItem(menu); } @@ -317,7 +417,7 @@ ResView::AddResource(const entry_ref &ref) ResDataRow *row = new ResDataRow(resData); fListView->AddRow(row); - fIsDirty = true; + SetSaveStatus(FILE_DIRTY); } @@ -325,9 +425,10 @@ void ResView::DeleteSelectedResources(void) { ResDataRow *selection = (ResDataRow*)fListView->CurrentSelection(); + if (!selection) + return; - if (selection) - fIsDirty = true; + SetSaveStatus(FILE_DIRTY); while (selection) { ResourceData *data = selection->GetData(); @@ -339,6 +440,27 @@ ResView::DeleteSelectedResources(void) } +void +ResView::SetSaveStatus(uint8 value) +{ + if (value == fSaveStatus) + return; + + fSaveStatus = value; + + BString title("ResEdit: "); + title << fFileName; + if (fSaveStatus == FILE_DIRTY) + title << "*"; + + if (Window()) { + Window()->Lock(); + Window()->SetTitle(title.String()); + Window()->Unlock(); + } +} + + ResDataRow::ResDataRow(ResourceData *data) : fResData(data) { diff --git a/src/apps/resedit/ResView.h b/src/apps/resedit/ResView.h index 175a6fcbe6..a15d8dc37d 100644 --- a/src/apps/resedit/ResView.h +++ b/src/apps/resedit/ResView.h @@ -19,11 +19,18 @@ #include "ResourceRoster.h" - class BMenuBar; class ResListView; -class ResView : public BView { +enum { + FILE_CLEAN = 0, + FILE_DIRTY, + FILE_INIT, + FILE_QUIT_AFTER_SAVE +}; + +class ResView : public BView +{ public: ResView(const BRect &frame, const char *name, const int32 &resize, const int32 &flags, @@ -33,9 +40,12 @@ public: void MessageReceived(BMessage *msg); const char * Filename(void) const { return fFileName.String(); } - bool IsDirty(void) const { return fIsDirty; } + uint8 GetSaveStatus(void) const { return fSaveStatus; } + status_t SetTo(const entry_ref &dir, const BString &name); void OpenFile(const entry_ref &ref); + void SaveFile(void); + void SaveAndQuit(void); private: void BuildMenus(BMenuBar *menuBar); @@ -44,21 +54,23 @@ private: void HandleDrop(BMessage *msg); void AddResource(const entry_ref &ref); void DeleteSelectedResources(void); + void SetSaveStatus(uint8 value); ResListView *fListView; entry_ref *fRef; BString fFileName; BMenuBar *fBar; - bool fIsDirty; + uint8 fSaveStatus; BList fDataList; - BFilePanel *fFilePanel; + BFilePanel *fOpenPanel, + *fSavePanel; }; + class ResDataRow : public BRow { public: ResDataRow(ResourceData *data); - ResourceData * GetData(void) const; private: diff --git a/src/apps/resedit/ResWindow.cpp b/src/apps/resedit/ResWindow.cpp index 6f0d64c558..f306837293 100644 --- a/src/apps/resedit/ResWindow.cpp +++ b/src/apps/resedit/ResWindow.cpp @@ -10,6 +10,8 @@ #include "App.h" #include "ResView.h" +#include + static int32 sWindowCount = 0; ResWindow::ResWindow(const BRect &rect, const entry_ref *ref) @@ -17,12 +19,8 @@ ResWindow::ResWindow(const BRect &rect, const entry_ref *ref) { atomic_add(&sWindowCount, 1); - ResView *child = new ResView(Bounds(), "resview", B_FOLLOW_ALL, - B_WILL_DRAW, ref); - AddChild(child); - - SetTitle(child->Filename()); - + fView = new ResView(Bounds(), "resview", B_FOLLOW_ALL, B_WILL_DRAW, ref); + AddChild(fView); Show(); } @@ -35,6 +33,20 @@ ResWindow::~ResWindow(void) bool ResWindow::QuitRequested(void) { + if (fView->GetSaveStatus() == FILE_DIRTY) { + BAlert *alert = new BAlert("ResEdit","Save your changes?","Cancel","Don't Save","Save"); + switch (alert->Go()) { + case 0: + return false; + case 2: { + fView->SaveAndQuit(); + return false; + } + default: + break; + } + } + atomic_add(&sWindowCount, -1); if (sWindowCount == 0) diff --git a/src/apps/resedit/ResWindow.h b/src/apps/resedit/ResWindow.h index cf9cbc9cbc..fc36d155cc 100644 --- a/src/apps/resedit/ResWindow.h +++ b/src/apps/resedit/ResWindow.h @@ -10,8 +10,8 @@ #include - struct entry_ref; +class ResView; class ResWindow : public BWindow { public: @@ -20,6 +20,8 @@ public: virtual ~ResWindow(); virtual bool QuitRequested(); +private: + ResView *fView; }; #endif // RESWIN_H