1/*
2 * Copyright 2006, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan A��mus <superstippi@gmx.de>
7 */
8
9#include "SavePanel.h"
10
11#include <stdio.h>
12#include <string.h>
13
14#include <Alert.h>
15#include <Button.h>
16#include <Catalog.h>
17#include <Locale.h>
18#include <MenuBar.h>
19#include <MenuField.h>
20#include <PopUpMenu.h>
21#include <ScrollBar.h>
22#include <TextControl.h>
23#include <TranslationKit.h>
24#include <View.h>
25#include <Window.h>
26
27#include "Exporter.h"
28#include "IconEditorApp.h"
29#include "Panel.h"
30
31
32#undef B_TRANSLATION_CONTEXT
33#define B_TRANSLATION_CONTEXT "Icon-O-Matic-SavePanel"
34
35
36enum {
37	MSG_FORMAT		= 'sfpf',
38	MSG_SETTINGS	= 'sfps',
39};
40
41// SaveItem class
42SaveItem::SaveItem(const char* name,
43				   BMessage* message,
44				   uint32 exportMode)
45	: BMenuItem(name, message),
46	  fExportMode(exportMode)
47{
48}
49
50// #pragma mark -
51
52// SavePanel class
53SavePanel::SavePanel(const char* name,
54					 BMessenger* target,
55					 entry_ref* startDirectory,
56					 uint32 nodeFlavors,
57					 bool allowMultipleSelection,
58					 BMessage* message,
59					 BRefFilter* filter,
60					 bool modal,
61					 bool hideWhenDone)
62	: BFilePanel(B_SAVE_PANEL, target, startDirectory,
63				 nodeFlavors, allowMultipleSelection,
64				 message, filter, modal, hideWhenDone),
65	  BHandler(name),
66	  fConfigWindow(NULL),
67	  fFormatM(NULL),
68	  fExportMode(EXPORT_MODE_ICON_RDEF)
69{
70	BWindow* window = Window();
71	if (!window || !window->Lock())
72		return;
73
74	// add this instance as BHandler to the window's looper
75	window->AddHandler(this);
76
77	// find a couple of important views and mess with their layout
78	BView* background = Window()->ChildAt(0);
79	if (background == NULL) {
80		printf("SavePanel::SavePanel() - couldn't find necessary controls.\n");
81		return;
82	}
83	BButton* cancel = dynamic_cast<BButton*>(
84		background->FindView("cancel button"));
85	BView* textview = background->FindView("text view");
86	BScrollBar* hscrollbar = dynamic_cast<BScrollBar*>(
87		background->FindView("HScrollBar"));
88
89	if (!cancel || !textview || !hscrollbar) {
90		printf("SavePanel::SavePanel() - couldn't find necessary controls.\n");
91		return;
92	}
93
94	_BuildMenu();
95
96	BRect rect = textview->Frame();
97	rect.top = cancel->Frame().top;
98	font_height fh;
99	be_plain_font->GetHeight(&fh);
100	rect.bottom = rect.top + fh.ascent + fh.descent + 5.0;
101
102	fFormatMF = new BMenuField(rect, "format popup", B_TRANSLATE("Format"),
103								fFormatM, true,
104								B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
105								B_WILL_DRAW | B_NAVIGABLE);
106	fFormatMF->SetDivider(be_plain_font->StringWidth(
107		B_TRANSLATE("Format")) + 7);
108	fFormatMF->MenuBar()->ResizeToPreferred();
109	fFormatMF->ResizeToPreferred();
110
111	float height = fFormatMF->Bounds().Height() + 8.0;
112
113	// find all the views that are in the way and
114	// move up them up the height of the menu field
115	BView *poseview = background->FindView("PoseView");
116	if (poseview) poseview->ResizeBy(0, -height);
117	BButton *insert = (BButton *)background->FindView("default button");
118	if (hscrollbar) hscrollbar->MoveBy(0, -height);
119	BScrollBar *vscrollbar = (BScrollBar *)background->FindView("VScrollBar");
120	if (vscrollbar) vscrollbar->ResizeBy(0, -height);
121	BView *countvw = (BView *)background->FindView("CountVw");
122	if (countvw) countvw->MoveBy(0, -height);
123	textview->MoveBy(0, -height);
124
125#if HAIKU_TARGET_PLATFORM_DANO
126	fFormatMF->MoveTo(textview->Frame().left, fFormatMF->Frame().top + 2);
127#else
128	fFormatMF->MoveTo(textview->Frame().left, fFormatMF->Frame().top);
129#endif
130
131	background->AddChild(fFormatMF);
132
133	// Build the "Settings" button relative to the format menu
134	rect = cancel->Frame();
135	rect.OffsetTo(fFormatMF->Frame().right + 5.0, rect.top);
136	fSettingsB = new BButton(rect, "settings",
137							 B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
138							 new BMessage(MSG_SETTINGS),
139							 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM,
140							 B_WILL_DRAW | B_NAVIGABLE);
141	fSettingsB->ResizeToPreferred();
142	background->AddChild(fSettingsB);
143	fSettingsB->SetTarget(this);
144
145	textview->ResizeTo(fSettingsB->Frame().right - fFormatMF->Frame().left,
146					   textview->Frame().Height());
147
148	// Make sure the smallest window won't draw the "Settings" button over
149	// anything else
150	float minWindowWidth = textview->Bounds().Width()
151							+ cancel->Bounds().Width()
152							+ (insert ? insert->Bounds().Width() : 0.0)
153							+ 90;
154	Window()->SetSizeLimits(minWindowWidth, 10000, 250, 10000);
155	if (Window()->Bounds().IntegerWidth() + 1 < minWindowWidth)
156		Window()->ResizeTo(minWindowWidth, Window()->Bounds().Height());
157
158
159	// Init window title
160	SetExportMode(true);
161
162	window->Unlock();
163}
164
165// destructor
166SavePanel::~SavePanel()
167{
168}
169
170// SendMessage
171void
172SavePanel::SendMessage(const BMessenger* messenger, BMessage* message)
173{
174	// add the current format information to the message,
175	// bot only if we are indeed in export mode
176	if (message && fFormatM->IsEnabled())
177		message->AddInt32("export mode", ExportMode());
178	// let the original file panel code handle the rest
179	BFilePanel::SendMessage(messenger, message);
180}
181
182// MessageReceived
183void
184SavePanel::MessageReceived(BMessage* message)
185{
186	// Handle messages from controls we've added
187	switch (message->what) {
188		case MSG_FORMAT:
189			fExportMode = ExportMode();
190			AdjustExtension();
191				// TODO: make this behaviour a setting
192			_EnableSettings();
193			break;
194		case MSG_SETTINGS:
195			_ExportSettings();
196			break;
197		default:
198			BHandler::MessageReceived(message);
199			break;
200	}
201}
202
203// SetExportMode
204void
205SavePanel::SetExportMode(bool exportMode)
206{
207	BWindow* window = Window();
208	if (!window || !window->Lock())
209		return;
210
211	// adjust window title and enable format menu
212	BString title("Icon-O-Matic: ");
213	if (exportMode) {
214		fFormatMF->SetEnabled(true);
215		SetExportMode(fExportMode);
216		_EnableSettings();
217		title << B_TRANSLATE_CONTEXT("Export icon", "Dialog title");
218	} else {
219		fExportMode = ExportMode();
220			// does not overwrite fExportMode in case we already were
221			// in native save mode
222		fNativeMI->SetMarked(true);
223
224		fFormatMF->SetEnabled(false);
225		fSettingsB->SetEnabled(false);
226		title << B_TRANSLATE_CONTEXT("Save icon", "Dialog title");
227	}
228
229	window->SetTitle(title);
230	window->Unlock();
231}
232
233// SetExportMode
234void
235SavePanel::SetExportMode(int32 mode)
236{
237	BWindow* window = Window();
238	if (!window || !window->Lock())
239		return;
240
241	switch (mode) {
242		case EXPORT_MODE_MESSAGE:
243			fNativeMI->SetMarked(true);
244			break;
245		case EXPORT_MODE_FLAT_ICON:
246			fHVIFMI->SetMarked(true);
247			break;
248		case EXPORT_MODE_SVG:
249			fSVGMI->SetMarked(true);
250			break;
251		case EXPORT_MODE_BITMAP_16:
252			fBitmap16MI->SetMarked(true);
253			break;
254		case EXPORT_MODE_BITMAP_32:
255			fBitmap32MI->SetMarked(true);
256			break;
257		case EXPORT_MODE_BITMAP_64:
258			fBitmap64MI->SetMarked(true);
259			break;
260		case EXPORT_MODE_BITMAP_SET:
261			fBitmapSetMI->SetMarked(true);
262			break;
263		case EXPORT_MODE_ICON_ATTR:
264			fIconAttrMI->SetMarked(true);
265			break;
266		case EXPORT_MODE_ICON_MIME_ATTR:
267			fIconMimeAttrMI->SetMarked(true);
268			break;
269		case EXPORT_MODE_ICON_RDEF:
270			fRDefMI->SetMarked(true);
271			break;
272		case EXPORT_MODE_ICON_SOURCE:
273			fSourceMI->SetMarked(true);
274			break;
275	}
276
277	if (mode != EXPORT_MODE_MESSAGE)
278		fExportMode = mode;
279
280	fFormatMF->SetEnabled(mode != EXPORT_MODE_MESSAGE);
281	_EnableSettings();
282
283	window->Unlock();
284}
285
286// ExportMode
287int32
288SavePanel::ExportMode() const
289{
290	int32 mode = fExportMode;
291	BWindow* window = Window();
292	if (!window || !window->Lock())
293		return mode;
294
295	if (fFormatMF->IsEnabled()) {
296		// means we are actually in export mode
297		SaveItem* item = _GetCurrentMenuItem();
298		mode = item->ExportMode();
299	}
300	window->Unlock();
301
302	return mode;
303}
304
305// AdjustExtension
306void
307SavePanel::AdjustExtension()
308{
309//	if (!Window()->Lock())
310//		return;
311//
312//	BView* background = Window()->ChildAt(0);
313//	BTextControl* textview = dynamic_cast<BTextControl*>(
314//		background->FindView("text view"));
315//
316//	if (textview) {
317//
318//		translator_id id = 0;
319//		uint32 format = 0;
320//		int32 mode = ExportMode();
321//		SaveItem* exportItem = dynamic_cast<SaveItem*>(_GetCurrentMenuItem());
322//		if (mode == EXPORT_TRANSLATOR && exportItem) {
323//			id = exportItem->id;
324//			format = exportItem->format;
325//		}
326//
327//		Exporter* exporter = Exporter::ExporterFor(mode, id, format);
328//
329//		if (exporter) {
330//			BString name(textview->Text());
331//
332//			// adjust the name extension
333//			const char* extension = exporter->Extension();
334//			if (strlen(extension) > 0) {
335//				int32 cutPos = name.FindLast('.');
336//				int32 cutCount = name.Length() - cutPos;
337//				if (cutCount > 0 && cutCount <= 4) {
338//					name.Remove(cutPos, cutCount);
339//				}
340//				name << "." << extension;
341//			}
342//
343//			SetSaveText(name.String());
344//		}
345//
346//		delete exporter;
347//	}
348//	Window()->Unlock();
349}
350
351// _GetCurrentMenuItem
352SaveItem*
353SavePanel::_GetCurrentMenuItem() const
354{
355	SaveItem* item = dynamic_cast<SaveItem*>(fFormatM->FindMarked());
356	if (!item)
357		return fNativeMI;
358	return item;
359}
360
361// _ExportSettings
362void
363SavePanel::_ExportSettings()
364{
365//	SaveItem *item = dynamic_cast<SaveItem*>(_GetCurrentMenuItem());
366//	if (item == NULL)
367//		return;
368//
369//	BTranslatorRoster *roster = BTranslatorRoster::Default();
370//	BView *view;
371//	BRect rect(0, 0, 239, 239);
372//
373//	// Build a window around this translator's configuration view
374//	status_t err = roster->MakeConfigurationView(item->id, NULL, &view, &rect);
375//	if (err < B_OK || view == NULL) {
376//		BAlert *alert = new BAlert(NULL, strerror(err), "OK");
377//		alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
378//		alert->Go();
379//	} else {
380//		if (fConfigWindow != NULL) {
381//			if (fConfigWindow->Lock())
382//				fConfigWindow->Quit();
383//		}
384//		fConfigWindow = new Panel(rect, "Translator Settings",
385//								  B_TITLED_WINDOW_LOOK,
386//								  B_NORMAL_WINDOW_FEEL,
387//								  B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
388//		fConfigWindow->AddChild(view);
389//		// Just to make sure
390//		view->MoveTo(0, 0);
391//		view->ResizeTo(rect.Width(), rect.Height());
392//		view->ResizeToPreferred();
393//		fConfigWindow->MoveTo(100, 100);
394//		fConfigWindow->Show();
395//	}
396}
397
398// _BuildMenu
399void
400SavePanel::_BuildMenu()
401{
402	fFormatM = new BPopUpMenu(B_TRANSLATE("Format"));
403
404	fNativeMI = new SaveItem("Icon-O-Matic",
405		new BMessage(MSG_FORMAT), EXPORT_MODE_MESSAGE);
406	fFormatM->AddItem(fNativeMI);
407	fNativeMI->SetEnabled(false);
408
409	fFormatM->AddSeparatorItem();
410
411	fHVIFMI = new SaveItem("HVIF",
412		new BMessage(MSG_FORMAT), EXPORT_MODE_FLAT_ICON);
413	fFormatM->AddItem(fHVIFMI);
414
415	fRDefMI = new SaveItem("HVIF RDef",
416		new BMessage(MSG_FORMAT), EXPORT_MODE_ICON_RDEF);
417	fFormatM->AddItem(fRDefMI);
418
419	fSourceMI = new SaveItem(B_TRANSLATE("HVIF Source Code"),
420		new BMessage(MSG_FORMAT), EXPORT_MODE_ICON_SOURCE);
421	fFormatM->AddItem(fSourceMI);
422
423	fFormatM->AddSeparatorItem();
424
425	fSVGMI = new SaveItem("SVG",
426		new BMessage(MSG_FORMAT), EXPORT_MODE_SVG);
427
428	fFormatM->AddItem(fSVGMI);
429
430	fFormatM->AddSeparatorItem();
431
432	fBitmap16MI = new SaveItem("PNG 16x16",
433		new BMessage(MSG_FORMAT), EXPORT_MODE_BITMAP_16);
434	fFormatM->AddItem(fBitmap16MI);
435
436	fBitmap32MI = new SaveItem("PNG 32x32",
437		new BMessage(MSG_FORMAT), EXPORT_MODE_BITMAP_32);
438	fFormatM->AddItem(fBitmap32MI);
439
440	fBitmap64MI = new SaveItem("PNG 64x64",
441		new BMessage(MSG_FORMAT), EXPORT_MODE_BITMAP_64);
442	fFormatM->AddItem(fBitmap64MI);
443
444	fBitmapSetMI = new SaveItem(B_TRANSLATE("PNG Set"),
445		new BMessage(MSG_FORMAT), EXPORT_MODE_BITMAP_SET);
446	fFormatM->AddItem(fBitmapSetMI);
447
448	fFormatM->AddSeparatorItem();
449
450	fIconAttrMI = new SaveItem(B_TRANSLATE("BEOS:ICON Attribute"),
451		new BMessage(MSG_FORMAT), EXPORT_MODE_ICON_ATTR);
452	fFormatM->AddItem(fIconAttrMI);
453
454	fIconMimeAttrMI = new SaveItem(B_TRANSLATE("META:ICON Attribute"),
455		new BMessage(MSG_FORMAT), EXPORT_MODE_ICON_MIME_ATTR);
456
457	fFormatM->AddItem(fIconMimeAttrMI);
458
459
460	fFormatM->SetTargetForItems(this);
461
462	// pick the RDef item in the list
463	fRDefMI->SetMarked(true);
464}
465
466// _EnableSettings
467void
468SavePanel::_EnableSettings() const
469{
470	// no settings currently necessary
471	fSettingsB->SetEnabled(false);
472}
473
474