xref: /haiku/src/apps/resedit/ResView.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2  * Copyright (c) 2005-2006, Haiku, Inc.
3  * Distributed under the terms of the MIT license.
4  *
5  * Author:
6  *		DarkWyrm <darkwyrm@earthlink.net>
7  */
8 #include "ResView.h"
9 
10 #include <Application.h>
11 #include <ScrollView.h>
12 #include <MenuBar.h>
13 #include <Menu.h>
14 #include <MenuItem.h>
15 #include <stdio.h>
16 #include <ColumnTypes.h>
17 
18 #include "App.h"
19 #include "ResourceData.h"
20 #include "ResFields.h"
21 #include "ResWindow.h"
22 #include "PreviewColumn.h"
23 #include "Editor.h"
24 
25 static int32 sUntitled = 1;
26 
27 ResourceRoster gResRoster;
28 
29 enum {
30 	M_NEW_FILE = 'nwfl',
31 	M_OPEN_FILE,
32 	M_SAVE_FILE,
33 	M_SAVE_FILE_AS,
34 	M_QUIT,
35 	M_EDIT_RESOURCE
36 };
37 
38 ResView::ResView(const BRect &frame, const char *name, const int32 &resize,
39 				const int32 &flags, const entry_ref *ref)
40   :	BView(frame, name, resize, flags),
41   	fIsDirty(false)
42 {
43 	SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
44 	if (ref) {
45 		fRef = new entry_ref;
46 		*fRef = *ref;
47 		fFileName = fRef->name;
48 	} else {
49 		fRef = NULL;
50 		fFileName = "Untitled ";
51 		fFileName << sUntitled;
52 		sUntitled++;
53 	}
54 
55 	BMenu *menu = new BMenu("File");
56 	menu->AddItem(new BMenuItem("New" B_UTF8_ELLIPSIS, new BMessage(M_NEW_FILE), 'N'));
57 	menu->AddSeparatorItem();
58 	menu->AddItem(new BMenuItem("Open" B_UTF8_ELLIPSIS, new BMessage(M_OPEN_FILE), 'O'));
59 	menu->AddItem(new BMenuItem("Quit", new BMessage(M_QUIT), 'Q'));
60 
61 	BRect r(Bounds());
62 	r.bottom = 16;
63 	fBar = new BMenuBar(r, "bar");
64 	AddChild(fBar);
65 
66 	fBar->AddItem(menu);
67 
68 	r = Bounds();
69 	r.top = fBar->Frame().bottom + 4;
70 	fListView = new BColumnListView(r, "gridview", B_FOLLOW_ALL, B_WILL_DRAW,
71 									B_FANCY_BORDER);
72 	AddChild(fListView);
73 
74 	rgb_color white = { 255,255,255,255 };
75 	fListView->SetColor(B_COLOR_BACKGROUND, white);
76 	fListView->SetColor(B_COLOR_SELECTION, ui_color(B_MENU_BACKGROUND_COLOR));
77 
78 	float width = be_plain_font->StringWidth("00000") + 20;
79 	fListView->AddColumn(new BStringColumn("ID",width,width,100,B_TRUNCATE_END),0);
80 
81 	fListView->AddColumn(new BStringColumn("Type",width,width,100,B_TRUNCATE_END),1);
82 	fListView->AddColumn(new BStringColumn("Name",150,50,300,B_TRUNCATE_END),2);
83 	fListView->AddColumn(new PreviewColumn("Data",150,50,300),3);
84 	fListView->SetInvocationMessage(new BMessage(M_EDIT_RESOURCE));
85 
86 	width = be_plain_font->StringWidth("1000 bytes") + 20;
87 	fListView->AddColumn(new BSizeColumn("Size",width,10,100),4);
88 
89 	if (ref)
90 		OpenFile(*ref);
91 }
92 
93 
94 ResView::~ResView(void)
95 {
96 	EmptyDataList();
97 	delete fRef;
98 }
99 
100 
101 void
102 ResView::AttachedToWindow(void)
103 {
104 	for(int32 i = 0; i < fBar->CountItems(); i++)
105 		fBar->SubmenuAt(i)->SetTargetForItems(this);
106 	fListView->SetTarget(this);
107 }
108 
109 
110 void
111 ResView::MessageReceived(BMessage *msg)
112 {
113 	if (msg->WasDropped()) {
114 		be_app->PostMessage(msg);
115 		return;
116 	}
117 
118 	switch (msg->what) {
119 		case M_NEW_FILE: {
120 			BRect r(100,100,400,400);
121 			if (Window())
122 				r = Window()->Frame().OffsetByCopy(10,10);
123 			ResWindow *win = new ResWindow(r);
124 			win->Show();
125 			break;
126 		}
127 		case M_OPEN_FILE: {
128 			be_app->PostMessage(M_SHOW_OPEN_PANEL);
129 			break;
130 		}
131 		case M_QUIT: {
132 			be_app->PostMessage(B_QUIT_REQUESTED);
133 			break;
134 		}
135 		case M_EDIT_RESOURCE: {
136 			BRow *row = fListView->CurrentSelection();
137 			TypeCodeField *field = (TypeCodeField*)row->GetField(1);
138 			gResRoster.SpawnEditor(field->GetResourceData(),this);
139 			break;
140 		}
141 		case M_UPDATE_RESOURCE: {
142 			ResourceData *item;
143 			if (msg->FindPointer("item",(void **)&item) != B_OK)
144 				break;
145 
146 			for (int32 i = 0; i < fListView->CountRows(); i++) {
147 				BRow *row = fListView->RowAt(i);
148 				TypeCodeField *field = (TypeCodeField*)row->GetField(1);
149 				if (!field || field->GetResourceData() != item)
150 					continue;
151 
152 				UpdateRow(row);
153 				break;
154 			}
155 			break;
156 		}
157 		default:
158 			BView::MessageReceived(msg);
159 	}
160 }
161 
162 
163 void
164 ResView::OpenFile(const entry_ref &ref)
165 {
166 	// Add all the 133t resources and attributes of the file
167 
168 	BFile file(&ref, B_READ_ONLY);
169 	BResources resources;
170 	if (resources.SetTo(&file) != B_OK)
171 		return;
172 	file.Unset();
173 
174 	resources.PreloadResourceType();
175 
176 	int32 index = 0;
177 	BRow *row;
178 	ResourceData *resData = new ResourceData();
179 	while (resData->SetFromResource(index, resources)) {
180 		row = new BRow();
181 		row->SetField(new BStringField(resData->GetIDString()),0);
182 		row->SetField(new TypeCodeField(resData->GetType(),resData),1);
183 		row->SetField(new BStringField(resData->GetName()),2);
184 		BField *field = gResRoster.MakeFieldForType(resData->GetType(),
185 													resData->GetData(),
186 													resData->GetLength());
187 		if (field)
188 			row->SetField(field,3);
189 		row->SetField(new BSizeField(resData->GetLength()),4);
190 		fListView->AddRow(row);
191 		fDataList.AddItem(resData);
192 		resData = new ResourceData();
193 		index++;
194 	}
195 	delete resData;
196 
197 	BNode node;
198 	if (node.SetTo(&ref) == B_OK) {
199 		char attrName[B_ATTR_NAME_LENGTH];
200 		node.RewindAttrs();
201 		resData = new ResourceData();
202 		while (node.GetNextAttrName(attrName) == B_OK) {
203 			if (resData->SetFromAttribute(attrName, node)) {
204 				row = new BRow();
205 				row->SetField(new BStringField(resData->GetIDString()),0);
206 				row->SetField(new TypeCodeField(resData->GetType(),resData),1);
207 				row->SetField(new BStringField(resData->GetName()),2);
208 				BField *field = gResRoster.MakeFieldForType(resData->GetType(),
209 															resData->GetData(),
210 															resData->GetLength());
211 				if (field)
212 					row->SetField(field,3);
213 				row->SetField(new BSizeField(resData->GetLength()),4);
214 				fListView->AddRow(row);
215 				fDataList.AddItem(resData);
216 				resData = new ResourceData();
217 			}
218 		}
219 		delete resData;
220 	}
221 }
222 
223 
224 void
225 ResView::EmptyDataList(void)
226 {
227 	for (int32 i = 0; i < fDataList.CountItems(); i++) {
228 		ResourceData *data = (ResourceData*) fDataList.ItemAt(i);
229 		delete data;
230 	}
231 	fDataList.MakeEmpty();
232 }
233 
234 
235 void
236 ResView::UpdateRow(BRow *row)
237 {
238 	TypeCodeField *typeField = (TypeCodeField*) row->GetField(1);
239 	ResourceData *resData = typeField->GetResourceData();
240 	BStringField *strField = (BStringField *)row->GetField(0);
241 
242 	if (strcmp("(attr)", strField->String()) != 0)
243 		strField->SetString(resData->GetIDString());
244 
245 	strField = (BStringField *)row->GetField(2);
246 	strField->SetString(resData->GetName());
247 
248 	PreviewField *preField = (PreviewField*)row->GetField(3);
249 	preField->SetData(resData->GetData(), resData->GetLength());
250 
251 	BSizeField *sizeField = (BSizeField*)row->GetField(4);
252 	sizeField->SetSize(resData->GetLength());
253 }
254