xref: /haiku/src/apps/icon-o-matic/gui/SavePanel.cpp (revision 60a6f1d5d7a8715cd3897dd0b626f2e4a64984a8)
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 
36 enum {
37 	MSG_FORMAT		= 'sfpf',
38 	MSG_SETTINGS	= 'sfps',
39 };
40 
41 // SaveItem class
42 SaveItem::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
53 SavePanel::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
166 SavePanel::~SavePanel()
167 {
168 }
169 
170 // SendMessage
171 void
172 SavePanel::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
183 void
184 SavePanel::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
204 void
205 SavePanel::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
234 void
235 SavePanel::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
287 int32
288 SavePanel::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
306 void
307 SavePanel::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
352 SaveItem*
353 SavePanel::_GetCurrentMenuItem() const
354 {
355 	SaveItem* item = dynamic_cast<SaveItem*>(fFormatM->FindMarked());
356 	if (!item)
357 		return fNativeMI;
358 	return item;
359 }
360 
361 // _ExportSettings
362 void
363 SavePanel::_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), B_TRANSLATE("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
399 void
400 SavePanel::_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
467 void
468 SavePanel::_EnableSettings() const
469 {
470 	// no settings currently necessary
471 	fSettingsB->SetEnabled(false);
472 }
473 
474