2 * Copyright (c) 2005-2010, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
6 * DarkWyrm <darkwyrm@gmail.com>
10 #include <Application.h>
15 #include <ScrollView.h>
16 #include <TranslatorRoster.h>
17 #include <TypeConstants.h>
23 #include "ColumnTypes.h"
24 #include "ResourceData.h"
25 #include "ResFields.h"
26 #include "ResListView.h"
27 #include "ResWindow.h"
28 #include "PreviewColumn.h"
31 static int32 sUntitled
= 1;
33 ResourceRoster gResRoster
;
45 ResView::ResView(const BRect
&frame
, const char *name
, const int32
&resize
,
46 const int32
&flags
, const entry_ref
*ref
)
47 : BView(frame
, name
, resize
, flags
),
49 fSaveStatus(FILE_INIT
),
53 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
57 fFileName
= fRef
->name
;
59 fFileName
= "Untitled ";
60 fFileName
<< sUntitled
;
66 fBar
= new BMenuBar(r
, "bar");
72 r
.top
= fBar
->Frame().bottom
+ 4;
73 fListView
= new ResListView(r
, "gridview", B_FOLLOW_ALL
, B_WILL_DRAW
, B_FANCY_BORDER
);
76 rgb_color white
= { 255, 255, 255, 255 };
77 fListView
->SetColor(B_COLOR_BACKGROUND
, white
);
78 fListView
->SetColor(B_COLOR_SELECTION
, ui_color(B_MENU_BACKGROUND_COLOR
));
80 float width
= be_plain_font
->StringWidth("00000") + 20;
81 fListView
->AddColumn(new BStringColumn("ID", width
, width
, 100, B_TRUNCATE_END
), 0);
83 fListView
->AddColumn(new BStringColumn("Type", width
, width
, 100, B_TRUNCATE_END
), 1);
84 fListView
->AddColumn(new BStringColumn("Name", 150, 50, 300, B_TRUNCATE_END
), 2);
85 fListView
->AddColumn(new PreviewColumn("Data", 150, 50, 300), 3);
87 // Editing is disabled for now
88 fListView
->SetInvocationMessage(new BMessage(M_EDIT_RESOURCE
));
90 width
= be_plain_font
->StringWidth("1000 bytes") + 20;
91 fListView
->AddColumn(new BSizeColumn("Size", width
, 10, 100), 4);
93 fOpenPanel
= new BFilePanel(B_OPEN_PANEL
);
97 fSavePanel
= new BFilePanel(B_SAVE_PANEL
);
101 ResView::~ResView(void)
111 ResView::AttachedToWindow(void)
113 for (int32 i
= 0; i
< fBar
->CountItems(); i
++)
114 fBar
->SubmenuAt(i
)->SetTargetForItems(this);
115 fListView
->SetTarget(this);
117 BMessenger
messenger(this);
118 fOpenPanel
->SetTarget(messenger
);
119 fSavePanel
->SetTarget(messenger
);
122 BString
title("ResEdit: ");
124 Window()->SetTitle(title
.String());
130 ResView::MessageReceived(BMessage
*msg
)
134 BRect
r(100, 100, 400, 400);
136 r
= Window()->Frame().OffsetByCopy(10, 10);
137 ResWindow
*win
= new ResWindow(r
);
142 be_app
->PostMessage(M_SHOW_OPEN_PANEL
);
146 if (fSaveStatus
== FILE_QUIT_AFTER_SAVE
)
147 SetSaveStatus(FILE_DIRTY
);
150 case B_SAVE_REQUESTED
: {
153 if (msg
->FindRef("directory",&saveDir
) == B_OK
&&
154 msg
->FindString("name",&name
) == B_OK
) {
167 case M_SHOW_SAVE_PANEL
: {
172 be_app
->PostMessage(B_QUIT_REQUESTED
);
175 case B_REFS_RECEIVED
: {
178 while (msg
->FindRef("refs", i
++, &ref
) == B_OK
)
182 case M_SELECT_FILE
: {
186 case M_DELETE_RESOURCE
: {
187 DeleteSelectedResources();
190 case M_EDIT_RESOURCE
: {
191 BRow
*row
= fListView
->CurrentSelection();
192 TypeCodeField
*field
= (TypeCodeField
*)row
->GetField(1);
193 gResRoster
.SpawnEditor(field
->GetResourceData(), this);
196 case M_UPDATE_RESOURCE
: {
198 if (msg
->FindPointer("item", (void **)&item
) != B_OK
)
201 for (int32 i
= 0; i
< fListView
->CountRows(); i
++) {
202 BRow
*row
= fListView
->RowAt(i
);
203 TypeCodeField
*field
= (TypeCodeField
*)row
->GetField(1);
204 if (!field
|| field
->GetResourceData() != item
)
213 BView::MessageReceived(msg
);
219 ResView::SetTo(const entry_ref
&dir
, const BString
&name
)
224 path
.Append(name
.String());
225 BFile
file(path
.Path(), B_CREATE_FILE
| B_READ_WRITE
);
226 if (file
.InitCheck() != B_OK
)
230 fRef
= new entry_ref();
232 BEntry
entry(path
.Path());
240 ResView::OpenFile(const entry_ref
&ref
)
242 // Add all the 133t resources and attributes of the file
243 BFile
file(&ref
, B_READ_ONLY
);
244 BResources resources
;
245 if (resources
.SetTo(&file
) != B_OK
)
249 resources
.PreloadResourceType();
253 ResourceData
*resData
= new ResourceData();
254 while (resData
->SetFromResource(index
, resources
)) {
255 row
= new ResDataRow(resData
);
256 fListView
->AddRow(row
);
257 fDataList
.AddItem(resData
);
258 resData
= new ResourceData();
264 if (node
.SetTo(&ref
) == B_OK
) {
265 char attrName
[B_ATTR_NAME_LENGTH
];
267 resData
= new ResourceData();
268 while (node
.GetNextAttrName(attrName
) == B_OK
) {
269 if (resData
->SetFromAttribute(attrName
, node
)) {
270 row
= new ResDataRow(resData
);
271 fListView
->AddRow(row
);
272 fDataList
.AddItem(resData
);
273 resData
= new ResourceData();
282 ResView::SaveFile(void)
284 if (fSaveStatus
== FILE_CLEAN
|| !fRef
)
287 BFile
file(fRef
,B_READ_WRITE
);
288 BResources
res(&file
,true);
291 for (int32 i
= 0; i
< fListView
->CountRows(); i
++) {
292 ResDataRow
*row
= (ResDataRow
*)fListView
->RowAt(i
);
293 ResourceData
*data
= row
->GetData();
294 res
.AddResource(data
->GetType(), data
->GetID(), data
->GetData(),
295 data
->GetLength(), data
->GetName());
300 if (fSaveStatus
== FILE_QUIT_AFTER_SAVE
&& Window())
301 Window()->PostMessage(B_QUIT_REQUESTED
);
302 SetSaveStatus(FILE_CLEAN
);
307 ResView::SaveAndQuit(void)
309 SetSaveStatus(FILE_QUIT_AFTER_SAVE
);
320 ResView::BuildMenus(BMenuBar
*menuBar
)
322 BMenu
*menu
= new BMenu("File");
323 menu
->AddItem(new BMenuItem("New" B_UTF8_ELLIPSIS
, new BMessage(M_NEW_FILE
), 'N'));
324 menu
->AddSeparatorItem();
325 menu
->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS
, new BMessage(M_OPEN_FILE
), 'O'));
326 menu
->AddSeparatorItem();
327 menu
->AddItem(new BMenuItem("Save", new BMessage(M_SAVE_FILE
), 'S'));
328 menu
->AddItem(new BMenuItem("Save As" B_UTF8_ELLIPSIS
, new BMessage(M_SHOW_SAVE_PANEL
), 'S',
329 B_COMMAND_KEY
| B_SHIFT_KEY
));
330 menuBar
->AddItem(menu
);
332 menu
= new BMenu("Resource");
333 menu
->AddItem(new BMenuItem("Add" B_UTF8_ELLIPSIS
, new BMessage(M_SELECT_FILE
), 'F'));
334 menu
->AddItem(new BMenuItem("Delete", new BMessage(M_DELETE_RESOURCE
), 'D'));
335 menuBar
->AddItem(menu
);
340 ResView::EmptyDataList(void)
342 for (int32 i
= 0; i
< fDataList
.CountItems(); i
++) {
343 ResourceData
*data
= (ResourceData
*) fDataList
.ItemAt(i
);
346 fDataList
.MakeEmpty();
351 ResView::UpdateRow(BRow
*row
)
353 TypeCodeField
*typeField
= (TypeCodeField
*) row
->GetField(1);
354 ResourceData
*resData
= typeField
->GetResourceData();
355 BStringField
*strField
= (BStringField
*)row
->GetField(0);
357 if (strcmp("(attr)", strField
->String()) != 0)
358 strField
->SetString(resData
->GetIDString());
360 strField
= (BStringField
*)row
->GetField(2);
362 strField
->SetString(resData
->GetName());
364 PreviewField
*preField
= (PreviewField
*)row
->GetField(3);
366 preField
->SetData(resData
->GetData(), resData
->GetLength());
368 BSizeField
*sizeField
= (BSizeField
*)row
->GetField(4);
370 sizeField
->SetSize(resData
->GetLength());
375 ResView::AddResource(const entry_ref
&ref
)
377 BFile
file(&ref
, B_READ_ONLY
);
378 if (file
.InitCheck() != B_OK
)
382 file
.ReadAttrString("BEOS:TYPE", &mime
);
384 if (mime
== "application/x-be-resource") {
385 BMessage
msg(B_REFS_RECEIVED
);
386 msg
.AddRef("refs", &ref
);
387 be_app
->PostMessage(&msg
);
391 type_code fileType
= 0;
393 BTranslatorRoster
*roster
= BTranslatorRoster::Default();
394 translator_info info
;
395 if (roster
->Identify(&file
, NULL
, &info
, 0, mime
.String()) == B_OK
)
396 fileType
= info
.type
;
398 fileType
= B_RAW_TYPE
;
401 for (int32 i
= 0; i
< fDataList
.CountItems(); i
++) {
402 ResourceData
*resData
= (ResourceData
*)fDataList
.ItemAt(i
);
403 if (resData
->GetType() == fileType
&& resData
->GetID() > lastID
)
404 lastID
= resData
->GetID();
408 file
.GetSize(&fileSize
);
413 char *fileData
= (char *)malloc(fileSize
);
414 file
.Read(fileData
, fileSize
);
416 ResourceData
*resData
= new ResourceData(fileType
, lastID
+ 1, ref
.name
,
418 fDataList
.AddItem(resData
);
420 ResDataRow
*row
= new ResDataRow(resData
);
421 fListView
->AddRow(row
);
423 SetSaveStatus(FILE_DIRTY
);
428 ResView::DeleteSelectedResources(void)
430 ResDataRow
*selection
= (ResDataRow
*)fListView
->CurrentSelection();
434 SetSaveStatus(FILE_DIRTY
);
437 ResourceData
*data
= selection
->GetData();
438 fListView
->RemoveRow(selection
);
439 fDataList
.RemoveItem(data
);
441 selection
= (ResDataRow
*)fListView
->CurrentSelection();
447 ResView::SetSaveStatus(uint8 value
)
449 if (value
== fSaveStatus
)
454 BString
title("ResEdit: ");
456 if (fSaveStatus
== FILE_DIRTY
)
461 Window()->SetTitle(title
.String());
467 ResDataRow::ResDataRow(ResourceData
*data
)
471 SetField(new BStringField(fResData
->GetIDString()), 0);
472 SetField(new TypeCodeField(fResData
->GetType(), fResData
), 1);
473 SetField(new BStringField(fResData
->GetName()), 2);
474 BField
*field
= gResRoster
.MakeFieldForType(fResData
->GetType(),
476 fResData
->GetLength());
479 SetField(new BSizeField(fResData
->GetLength()), 4);
485 ResDataRow::GetData(void) const