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