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