1/*
2 * Copyright 2008-2010, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Michael Pfeiffer <laplace@users.sourceforge.net>
7 */
8
9
10#include "FileSelectionPage.h"
11
12#include <string.h>
13
14#include <Button.h>
15#include <Catalog.h>
16#include <ControlLook.h>
17#include <Path.h>
18#include <RadioButton.h>
19#include <TextControl.h>
20#include <TextView.h>
21
22
23#undef B_TRANSLATION_CONTEXT
24#define B_TRANSLATION_CONTEXT "FileSelectionPage"
25
26
27const uint32 kMsgOpenFilePanel = 'open';
28
29
30FileSelectionPage::FileSelectionPage(BMessage* settings, BRect frame,
31	const char* name, const char* description, file_panel_mode mode)
32	:
33	WizardPageView(settings, frame, name, B_FOLLOW_ALL,
34		B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE),
35	fMode(mode),
36	fFilePanel(NULL)
37{
38	_BuildUI(description);
39}
40
41
42FileSelectionPage::~FileSelectionPage()
43{
44}
45
46
47void
48FileSelectionPage::FrameResized(float width, float height)
49{
50	WizardPageView::FrameResized(width, height);
51	_Layout();
52}
53
54
55void
56FileSelectionPage::AttachedToWindow()
57{
58	fSelect->SetTarget(this);
59}
60
61
62void
63FileSelectionPage::MessageReceived(BMessage* message)
64{
65	switch (message->what) {
66		case kMsgOpenFilePanel:
67			_OpenFilePanel();
68			break;
69		case B_REFS_RECEIVED:
70		case B_SAVE_REQUESTED:
71			_SetFileFromFilePanelMessage(message);
72			break;
73		case B_CANCEL:
74			_FilePanelCanceled();
75			break;
76		default:
77			WizardPageView::MessageReceived(message);
78	}
79}
80
81
82void
83FileSelectionPage::PageCompleted()
84{
85	fSettings->ReplaceString("file", fFile->Text());
86}
87
88
89const float kFileButtonDistance = 10;
90
91void
92FileSelectionPage::_BuildUI(const char* description)
93{
94	const float kSpacing = be_control_look->DefaultItemSpacing();
95	BRect rect(Bounds());
96
97	fDescription = CreateDescription(rect, "description", description);
98
99	MakeHeading(fDescription);
100	AddChild(fDescription);
101
102	BString file;
103	fSettings->FindString("file", &file);
104
105	fSelect = new BButton(rect, "select",
106		B_TRANSLATE_COMMENT("Select", "Button"),
107		new BMessage(kMsgOpenFilePanel),
108		B_FOLLOW_RIGHT);
109	fSelect->ResizeToPreferred();
110
111	float selectLeft = rect.right - fSelect->Bounds().Width();
112	rect.right = selectLeft - kSpacing;
113	fFile = new BTextControl(rect, "file",
114		B_TRANSLATE_COMMENT("File:", "Text control label"),
115		file.String(), new BMessage());
116	fFile->SetDivider(be_plain_font->StringWidth(fFile->Label()) + 5);
117	AddChild(fFile);
118
119	fSelect->MoveTo(selectLeft, 0);
120	AddChild(fSelect);
121
122	_Layout();
123}
124
125
126void
127FileSelectionPage::_Layout()
128{
129	const float kSpacing = be_control_look->DefaultItemSpacing();
130	LayoutDescriptionVertically(fDescription);
131
132	float left = fFile->Frame().left;
133	float top = fDescription->Frame().bottom + kSpacing;
134
135	// center "file" text field and "select" button vertically
136	float selectTop = top;
137	float fileTop = top;
138	float fileHeight = fFile->Bounds().Height();
139	float selectHeight = fSelect->Bounds().Height();
140	if (fileHeight < selectHeight) {
141		int delta = (int)((selectHeight - fileHeight + 1) / 2);
142		fileTop += delta;
143	} else {
144		int delta = (int)((fileHeight - selectHeight + 1) / 2);
145		selectTop += delta;
146	}
147
148	fFile->MoveTo(left, fileTop);
149
150	float width = fSelect->Frame().left - kSpacing - left;
151	fFile->ResizeTo(width, fileHeight);
152
153	left = fSelect->Frame().left;
154	fSelect->MoveTo(left, selectTop);
155}
156
157
158void
159FileSelectionPage::_OpenFilePanel()
160{
161	if (fFilePanel != NULL)
162		return;
163
164	const entry_ref* directory = NULL;
165	entry_ref base;
166	BPath file(fFile->Text());
167	BPath parent;
168
169	if (file.GetParent(&parent) == B_OK &&
170		get_ref_for_path(parent.Path(), &base) == B_OK)
171		directory = &base;
172
173	BMessenger messenger(this);
174	fFilePanel = new BFilePanel(fMode, &messenger, directory,
175		B_FILE_NODE, false, NULL, NULL, true);
176	if (fMode == B_SAVE_PANEL && file.Leaf() != NULL)
177		fFilePanel->SetSaveText(file.Leaf());
178	fFilePanel->Show();
179}
180
181
182void
183FileSelectionPage::_SetFileFromFilePanelMessage(BMessage* message)
184{
185	if (message->what == B_SAVE_REQUESTED) {
186		entry_ref directory;
187		BString name;
188		message->FindRef("directory", &directory);
189		message->FindString("name", &name);
190		BPath path(&directory);
191		if (path.Append(name.String()) == B_OK)
192			fFile->SetText(path.Path());
193	} else {
194		entry_ref entryRef;
195		message->FindRef("refs", &entryRef);
196		BEntry entry(&entryRef);
197		BPath path;
198		if (entry.GetPath(&path) == B_OK)
199			fFile->SetText(path.Path());
200	}
201}
202
203
204void
205FileSelectionPage::_FilePanelCanceled()
206{
207	delete fFilePanel;
208	fFilePanel = NULL;
209}
210