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 <GroupView.h>
18#include <LayoutBuilder.h>
19#include <Locale.h>
20#include <MenuBar.h>
21#include <MenuItem.h>
22#include <StringView.h>
23#include <TabView.h>
24#include <Volume.h>
25
26
27#undef B_TRANSLATION_CONTEXT
28#define B_TRANSLATION_CONTEXT "AttributeWindow"
29
30
31static const uint32 kMsgRemoveAttribute = 'rmat';
32
33
34class EditorTabView : public BTabView {
35	public:
36		EditorTabView(const char *name,
37			button_width width = B_WIDTH_FROM_WIDEST,
38			uint32 flags = B_WILL_DRAW | B_FRAME_EVENTS);
39
40		void AddRawEditorTab(BView *view);
41		void SetTypeEditorTab(BView *view);
42};
43
44
45// -----------------
46
47
48EditorTabView::EditorTabView(const char *name, button_width width, uint32 flags)
49	: BTabView(name, width, flags)
50{
51	SetBorder(B_NO_BORDER);
52}
53
54
55void
56EditorTabView::AddRawEditorTab(BView *view)
57{
58	BTab* tab = new BTab(view);
59	tab->SetLabel(B_TRANSLATE("Raw editor"));
60	AddTab(view, tab);
61}
62
63
64void
65EditorTabView::SetTypeEditorTab(BView *view)
66{
67	if (view == NULL) {
68		view = new BStringView(B_TRANSLATE("Type editor"),
69			B_TRANSLATE("No type editor available"));
70		((BStringView*)view)->SetAlignment(B_ALIGN_CENTER);
71	}
72
73	BGroupView* group = new BGroupView(B_VERTICAL);
74		BLayoutBuilder::Group<>(group, B_VERTICAL)
75		.SetInsets(B_USE_WINDOW_SPACING, 0, B_USE_WINDOW_SPACING, 0)
76		.Add(view)
77		.AddGlue(25.0f);
78
79	group->SetName(view->Name());
80
81	AddTab(group);
82	Select(0);
83}
84
85
86//	#pragma mark -
87
88
89AttributeWindow::AttributeWindow(BRect _rect, entry_ref *ref,
90	const char *attribute, const BMessage *settings)
91	: ProbeWindow(_rect, ref),
92	fAttribute(strdup(attribute))
93{
94	// Set alternative window title for devices
95	char name[B_FILE_NAME_LENGTH];
96	strlcpy(name, ref->name, sizeof(name));
97
98	BEntry entry(ref);
99	if (entry.IsDirectory()) {
100		BDirectory directory(&entry);
101		if (directory.InitCheck() == B_OK && directory.IsRootDirectory()) {
102			// use the volume name for root directories
103			BVolume volume;
104			if (directory.GetVolume(&volume) == B_OK)
105				volume.GetName(name);
106		}
107	}
108	char buffer[B_PATH_NAME_LENGTH];
109	snprintf(buffer, sizeof(buffer), "%s: %s", name, attribute);
110	SetTitle(buffer);
111
112	BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 0);
113	SetLayout(layout);
114
115	// add the menu
116
117	BMenuBar *menuBar = new BMenuBar("");
118	layout->AddView(menuBar, 0);
119
120	BMenu *menu = new BMenu(B_TRANSLATE("Attribute"));
121
122	// the ProbeView save menu items will be inserted here
123	menu->AddItem(new BMenuItem(B_TRANSLATE("Remove from file"),
124		new BMessage(kMsgRemoveAttribute)));
125	menu->AddSeparatorItem();
126
127	// the ProbeView print menu items will be inserted here
128	menu->AddSeparatorItem();
129
130	menu->AddItem(new BMenuItem(B_TRANSLATE("Close"),
131		new BMessage(B_CLOSE_REQUESTED), 'W', B_COMMAND_KEY));
132	menu->SetTargetForItems(this);
133	menuBar->AddItem(menu);
134
135	// add our interface widgets
136
137	EditorTabView *tabView = new EditorTabView("tabView");
138	layout->AddView(tabView, 999);
139
140	BRect rect = tabView->ContainerView()->Bounds();
141	rect.top += 3;
142
143	fProbeView = new ProbeView(ref, attribute, settings);
144	fProbeView->AddSaveMenuItems(menu, 0);
145	fProbeView->AddPrintMenuItems(menu, menu->CountItems() - 2);
146
147	fTypeEditorView = GetTypeEditorFor(rect, fProbeView->Editor());
148
149	tabView->SetTypeEditorTab(fTypeEditorView);
150	tabView->AddRawEditorTab(fProbeView);
151
152	if (fTypeEditorView == NULL) {
153		// show the raw editor if we don't have a specialised type editor
154		tabView->Select(1);
155	}
156}
157
158
159AttributeWindow::~AttributeWindow()
160{
161	free(fAttribute);
162}
163
164
165void
166AttributeWindow::MessageReceived(BMessage *message)
167{
168	switch (message->what) {
169		case kMsgRemoveAttribute:
170		{
171			char buffer[1024];
172
173			snprintf(buffer, sizeof(buffer),
174				B_TRANSLATE("Do you really want to remove the attribute \"%s\" "
175				"from the file \"%s\"?\n\nYou cannot undo this action."),
176				fAttribute, Ref().name);
177
178			BAlert* alert = new BAlert(B_TRANSLATE("DiskProbe request"),
179				buffer, B_TRANSLATE("Cancel"), B_TRANSLATE("Remove"), NULL,
180				B_WIDTH_AS_USUAL, B_WARNING_ALERT);
181			alert->SetShortcut(0, B_ESCAPE);
182			int32 chosen = alert->Go();
183
184			if (chosen == 1) {
185				BNode node(&Ref());
186				if (node.InitCheck() == B_OK)
187					node.RemoveAttr(fAttribute);
188
189				PostMessage(B_QUIT_REQUESTED);
190			}
191			break;
192		}
193
194		default:
195			ProbeWindow::MessageReceived(message);
196			break;
197	}
198}
199
200
201bool
202AttributeWindow::QuitRequested()
203{
204	if (fTypeEditorView != NULL)
205		fTypeEditorView->CommitChanges();
206
207	bool quit = fProbeView->QuitRequested();
208	if (!quit)
209		return false;
210
211	return ProbeWindow::QuitRequested();
212}
213
214
215bool
216AttributeWindow::Contains(const entry_ref &ref, const char *attribute)
217{
218	return ref == Ref() && attribute != NULL && !strcmp(attribute, fAttribute);
219}
220
221