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