xref: /haiku/src/apps/diskprobe/AttributeWindow.cpp (revision 922e7ba1f3228e6f28db69b0ded8f86eb32dea17)
1 /*
2  * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "AttributeWindow.h"
8 #include "ProbeView.h"
9 #include "TypeEditors.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 #include <Alert.h>
15 #include <Catalog.h>
16 #include <Directory.h>
17 #include <Locale.h>
18 #include <MenuBar.h>
19 #include <MenuItem.h>
20 #include <StringView.h>
21 #include <TabView.h>
22 #include <Volume.h>
23 
24 
25 #undef B_TRANSLATE_CONTEXT
26 #define B_TRANSLATE_CONTEXT "AttributeWindow"
27 
28 
29 static const uint32 kMsgRemoveAttribute = 'rmat';
30 
31 
32 class EditorTabView : public BTabView {
33 	public:
34 		EditorTabView(BRect frame, const char *name,
35 			button_width width = B_WIDTH_AS_USUAL,
36 			uint32 resizingMode = B_FOLLOW_ALL,
37 			uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS);
38 
39 		virtual void FrameResized(float width, float height);
40 		virtual void Select(int32 tab);
41 
42 		void AddRawEditorTab(BView *view);
43 		void SetTypeEditorTab(BView *view);
44 
45 	private:
46 		BView		*fRawEditorView;
47 		BView		*fTypeEditorView;
48 		BStringView	*fNoEditorView;
49 		int32		fRawTab;
50 };
51 
52 
53 //-----------------
54 
55 
56 EditorTabView::EditorTabView(BRect frame, const char *name, button_width width,
57 	uint32 resizingMode, uint32 flags)
58 	: BTabView(frame, name, width, resizingMode, flags),
59 	fRawEditorView(NULL),
60 	fRawTab(-1)
61 {
62 	ContainerView()->MoveBy(-ContainerView()->Frame().left,
63 		TabHeight() + 1 - ContainerView()->Frame().top);
64 	fNoEditorView = new BStringView(ContainerView()->Bounds(),
65 		B_TRANSLATE("Type editor"), B_TRANSLATE("No type editor available"),
66 		B_FOLLOW_NONE);
67 	fNoEditorView->ResizeToPreferred();
68 	fNoEditorView->SetAlignment(B_ALIGN_CENTER);
69 	fTypeEditorView = fNoEditorView;
70 
71 	FrameResized(0, 0);
72 
73 	SetTypeEditorTab(NULL);
74 }
75 
76 
77 void
78 EditorTabView::FrameResized(float width, float height)
79 {
80 	BRect rect = Bounds();
81 	rect.top = ContainerView()->Frame().top;
82 
83 	ContainerView()->ResizeTo(rect.Width(), rect.Height());
84 
85 	BView *view = fTypeEditorView;
86 	if (view == NULL)
87 		view = fNoEditorView;
88 
89 	BPoint point = view->Frame().LeftTop();
90 	if ((view->ResizingMode() & B_FOLLOW_RIGHT) == 0)
91 		point.x = (rect.Width() - view->Bounds().Width()) / 2;
92 	if ((view->ResizingMode() & B_FOLLOW_BOTTOM) == 0)
93 		point.y = (rect.Height() - view->Bounds().Height()) / 2;
94 
95 	view->MoveTo(point);
96 }
97 
98 
99 void
100 EditorTabView::Select(int32 tab)
101 {
102 	if (tab != fRawTab && fRawEditorView != NULL && !fRawEditorView->IsHidden(fRawEditorView))
103 		fRawEditorView->Hide();
104 
105 	BTabView::Select(tab);
106 
107 	BView *view;
108 	if (tab == fRawTab && fRawEditorView != NULL) {
109 		if (fRawEditorView->IsHidden(fRawEditorView))
110 			fRawEditorView->Show();
111 		view = fRawEditorView;
112 	} else
113 		view = ViewForTab(Selection());
114 
115 	if (view != NULL && (view->ResizingMode() & (B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM)) != 0) {
116 		BRect rect = ContainerView()->Bounds();
117 
118 		BRect frame = view->Frame();
119 		rect.left = frame.left;
120 		rect.top = frame.top;
121 		if ((view->ResizingMode() & B_FOLLOW_RIGHT) == 0)
122 			rect.right = frame.right;
123 		if ((view->ResizingMode() & B_FOLLOW_BOTTOM) == 0)
124 			rect.bottom = frame.bottom;
125 
126 		view->ResizeTo(rect.Width(), rect.Height());
127 	}
128 }
129 
130 
131 void
132 EditorTabView::AddRawEditorTab(BView *view)
133 {
134 	fRawEditorView = view;
135 	if (view != NULL)
136 		ContainerView()->AddChild(view);
137 
138 	fRawTab = CountTabs();
139 
140 	view = new BView(BRect(0, 0, 5, 5), B_TRANSLATE("Raw editor"), B_FOLLOW_NONE, 0);
141 	view->SetViewColor(ViewColor());
142 	AddTab(view);
143 }
144 
145 
146 void
147 EditorTabView::SetTypeEditorTab(BView *view)
148 {
149 	if (fTypeEditorView == view)
150 		return;
151 
152 	BTab *tab = TabAt(0);
153 	if (tab != NULL)
154 		tab->SetView(NULL);
155 
156 	fTypeEditorView = view;
157 
158 	if (view == NULL)
159 		view = fNoEditorView;
160 
161 	if (CountTabs() == 0)
162 		AddTab(view);
163 	else
164 		tab->SetView(view);
165 
166 	FrameResized(0, 0);
167 
168 #ifdef HAIKU_TARGET_PLATFORM_BEOS
169 	if (Window() != NULL) {
170 		// With R5's BTabView, calling select without being
171 		// attached to a window crashes...
172 		Select(0);
173 	}
174 #else
175 	Select(0);
176 #endif
177 }
178 
179 
180 //	#pragma mark -
181 
182 
183 AttributeWindow::AttributeWindow(BRect _rect, entry_ref *ref, const char *attribute,
184 	const BMessage *settings)
185 	: ProbeWindow(_rect, ref),
186 	fAttribute(strdup(attribute))
187 {
188 	// Set alternative window title for devices
189 
190 	char name[B_FILE_NAME_LENGTH];
191 #ifdef HAIKU_TARGET_PLATFORM_BEOS
192 	strncpy(name, ref->name, sizeof(name));
193 	name[sizeof(name) - 1] = '\0';
194 #else
195 	strlcpy(name, ref->name, sizeof(name));
196 #endif
197 
198 	BEntry entry(ref);
199 	if (entry.IsDirectory()) {
200 		BDirectory directory(&entry);
201 		if (directory.InitCheck() == B_OK && directory.IsRootDirectory()) {
202 			// use the volume name for root directories
203 			BVolume volume;
204 			if (directory.GetVolume(&volume) == B_OK)
205 				volume.GetName(name);
206 		}
207 	}
208 	char buffer[B_PATH_NAME_LENGTH];
209 	snprintf(buffer, sizeof(buffer), "%s: %s", name, attribute);
210 	SetTitle(buffer);
211 
212 	// add the menu
213 
214 	BMenuBar *menuBar = new BMenuBar(BRect(0, 0, 0, 0), NULL);
215 	AddChild(menuBar);
216 
217 	BMenu *menu = new BMenu(B_TRANSLATE("Attribute"));
218 
219 	// the ProbeView save menu items will be inserted here
220 	menu->AddItem(new BMenuItem(B_TRANSLATE("Remove from file"),
221 		new BMessage(kMsgRemoveAttribute)));
222 	menu->AddSeparatorItem();
223 
224 	// the ProbeView print menu items will be inserted here
225 	menu->AddSeparatorItem();
226 
227 	menu->AddItem(new BMenuItem(B_TRANSLATE("Close"), new BMessage(B_CLOSE_REQUESTED),
228 		'W', B_COMMAND_KEY));
229 	menu->SetTargetForItems(this);
230 	menuBar->AddItem(menu);
231 
232 	// add our interface widgets
233 
234 	BRect rect = Bounds();
235 	rect.top = menuBar->Bounds().Height() + 1;
236 
237 	BView *view = new BView(rect, "main", B_FOLLOW_ALL, 0);
238 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
239 	AddChild(view);
240 
241 	rect = view->Bounds();
242 	rect.top += 3;
243 
244 	EditorTabView *tabView = new EditorTabView(rect, "tabView");
245 
246 	rect = tabView->ContainerView()->Bounds();
247 	rect.top += 3;
248 	fProbeView = new ProbeView(rect, ref, attribute, settings);
249 	tabView->AddRawEditorTab(fProbeView);
250 
251 	view->AddChild(tabView);
252 
253 	fTypeEditorView = GetTypeEditorFor(rect, fProbeView->Editor());
254 	if (fTypeEditorView != NULL)
255 		tabView->SetTypeEditorTab(fTypeEditorView);
256 	else {
257 		// show the raw editor if we don't have a specialised type editor
258 		tabView->Select(1);
259 	}
260 
261 	fProbeView->AddSaveMenuItems(menu, 0);
262 	fProbeView->AddPrintMenuItems(menu, menu->CountItems() - 2);
263 
264 	fProbeView->UpdateSizeLimits();
265 }
266 
267 
268 AttributeWindow::~AttributeWindow()
269 {
270 	free(fAttribute);
271 }
272 
273 
274 void
275 AttributeWindow::MessageReceived(BMessage *message)
276 {
277 	switch (message->what) {
278 		case kMsgRemoveAttribute:
279 		{
280 			char buffer[1024];
281 			snprintf(buffer, sizeof(buffer),
282 				B_TRANSLATE("Do you really want to remove the attribute \"%s\" from "
283 				"the file \"%s\"?\n\nYou cannot undo this action."),
284 				fAttribute, Ref().name);
285 
286 			int32 chosen = (new BAlert(B_TRANSLATE("DiskProbe request"),
287 				buffer, B_TRANSLATE("Cancel"), B_TRANSLATE("Remove"), NULL,
288 				B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
289 			if (chosen == 1) {
290 				BNode node(&Ref());
291 				if (node.InitCheck() == B_OK)
292 					node.RemoveAttr(fAttribute);
293 
294 				PostMessage(B_QUIT_REQUESTED);
295 			}
296 			break;
297 		}
298 
299 		default:
300 			ProbeWindow::MessageReceived(message);
301 			break;
302 	}
303 }
304 
305 
306 bool
307 AttributeWindow::QuitRequested()
308 {
309 	if (fTypeEditorView != NULL)
310 		fTypeEditorView->CommitChanges();
311 
312 	bool quit = fProbeView->QuitRequested();
313 	if (!quit)
314 		return false;
315 
316 	return ProbeWindow::QuitRequested();
317 }
318 
319 
320 bool
321 AttributeWindow::Contains(const entry_ref &ref, const char *attribute)
322 {
323 	return ref == Ref() && attribute != NULL && !strcmp(attribute, fAttribute);
324 }
325 
326