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