xref: /haiku/src/apps/icon-o-matic/gui/SavePanel.cpp (revision 0c93c0a807b27096abbfad677436afb7d1712d4a)
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 			fExportMode = ExportMode();
171 			AdjustExtension();
172 				// TODO: make this behaviour a setting
173 			_EnableSettings();
174 			break;
175 		case MSG_SETTINGS:
176 			_ExportSettings();
177 			break;
178 		default:
179 			BHandler::MessageReceived(message);
180 			break;
181 	}
182 }
183 
184 // SetExportMode
185 void
186 SavePanel::SetExportMode(bool exportMode)
187 {
188 	BWindow* window = Window();
189 	if (!window || !window->Lock())
190 		return;
191 
192 	// adjust window title and enable format menu
193 	BString helper("Icon-O-Matic: ");
194 	if (exportMode) {
195 		fFormatMF->SetEnabled(true);
196 		SetExportMode(fExportMode);
197 		_EnableSettings();
198 		helper << "Export Icon";
199 	} else {
200 		fExportMode = ExportMode();
201 			// does not overwrite fExportMode in case we already were
202 			// in native save mode
203 		fNativeMI->SetMarked(true);
204 
205 		fFormatMF->SetEnabled(false);
206 		fSettingsB->SetEnabled(false);
207 		helper << "Save Icon";
208 	}
209 
210 	window->Unlock();
211 }
212 
213 // SetExportMode
214 void
215 SavePanel::SetExportMode(int32 mode)
216 {
217 	BWindow* window = Window();
218 	if (!window || !window->Lock())
219 		return;
220 
221 	switch (mode) {
222 		case EXPORT_MODE_MESSAGE:
223 			fNativeMI->SetMarked(true);
224 			break;
225 		case EXPORT_MODE_FLAT_ICON:
226 			fHVIFMI->SetMarked(true);
227 			break;
228 		case EXPORT_MODE_SVG:
229 			fSVGMI->SetMarked(true);
230 			break;
231 		case EXPORT_MODE_BITMAP:
232 			fBitmapMI->SetMarked(true);
233 			break;
234 		case EXPORT_MODE_BITMAP_SET:
235 			fBitmapSetMI->SetMarked(true);
236 			break;
237 		case EXPORT_MODE_ICON_ATTR:
238 			fIconAttrMI->SetMarked(true);
239 			break;
240 		case EXPORT_MODE_ICON_MIME_ATTR:
241 			fIconMimeAttrMI->SetMarked(true);
242 			break;
243 		case EXPORT_MODE_ICON_RDEF:
244 			fRDefMI->SetMarked(true);
245 			break;
246 	}
247 
248 	if (mode != EXPORT_MODE_MESSAGE)
249 		fExportMode = mode;
250 
251 	fFormatMF->SetEnabled(mode != EXPORT_MODE_MESSAGE);
252 	_EnableSettings();
253 
254 	window->Unlock();
255 }
256 
257 // ExportMode
258 int32
259 SavePanel::ExportMode() const
260 {
261 	int32 mode = fExportMode;
262 	BWindow* window = Window();
263 	if (!window || !window->Lock())
264 		return mode;
265 
266 	if (fFormatMF->IsEnabled()) {
267 		// means we are actually in export mode
268 		SaveItem* item = _GetCurrentMenuItem();
269 		mode = item->ExportMode();
270 	}
271 	window->Unlock();
272 
273 	return mode;
274 }
275 
276 // AdjustExtension
277 void
278 SavePanel::AdjustExtension()
279 {
280 //	if (!Window()->Lock())
281 //		return;
282 //
283 //	BView* background = Window()->ChildAt(0);
284 //	BTextControl* textview = dynamic_cast<BTextControl*>(
285 //		background->FindView("text view"));
286 //
287 //	if (textview) {
288 //
289 //		translator_id id = 0;
290 //		uint32 format = 0;
291 //		int32 mode = ExportMode();
292 //		SaveItem* exportItem = dynamic_cast<SaveItem*>(_GetCurrentMenuItem());
293 //		if (mode == EXPORT_TRANSLATOR && exportItem) {
294 //			id = exportItem->id;
295 //			format = exportItem->format;
296 //		}
297 //
298 //		Exporter* exporter = Exporter::ExporterFor(mode, id, format);
299 //
300 //		if (exporter) {
301 //			BString name(textview->Text());
302 //
303 //			// adjust the name extension
304 //			const char* extension = exporter->Extension();
305 //			if (strlen(extension) > 0) {
306 //				int32 cutPos = name.FindLast('.');
307 //				int32 cutCount = name.Length() - cutPos;
308 //				if (cutCount > 0 && cutCount <= 4) {
309 //					name.Remove(cutPos, cutCount);
310 //				}
311 //				name << "." << extension;
312 //			}
313 //
314 //			SetSaveText(name.String());
315 //		}
316 //
317 //		delete exporter;
318 //	}
319 //	Window()->Unlock();
320 }
321 
322 // _GetCurrentMenuItem
323 SaveItem*
324 SavePanel::_GetCurrentMenuItem() const
325 {
326 	SaveItem* item = dynamic_cast<SaveItem*>(fFormatM->FindMarked());
327 	if (!item)
328 		return fNativeMI;
329 	return item;
330 }
331 
332 // _ExportSettings
333 void
334 SavePanel::_ExportSettings()
335 {
336 //	SaveItem *item = dynamic_cast<SaveItem*>(_GetCurrentMenuItem());
337 //	if (item == NULL)
338 //		return;
339 //
340 //	BTranslatorRoster *roster = BTranslatorRoster::Default();
341 //	BView *view;
342 //	BRect rect(0, 0, 239, 239);
343 //
344 //	// Build a window around this translator's configuration view
345 //	status_t err = roster->MakeConfigurationView(item->id, NULL, &view, &rect);
346 //	if (err < B_OK || view == NULL) {
347 //		BAlert *alert = new BAlert(NULL, strerror(err), "OK");
348 //		alert->Go();
349 //	} else {
350 //		if (fConfigWindow != NULL) {
351 //			if (fConfigWindow->Lock())
352 //				fConfigWindow->Quit();
353 //		}
354 //		fConfigWindow = new Panel(rect, "Translator Settings",
355 //								  B_TITLED_WINDOW_LOOK,
356 //								  B_NORMAL_WINDOW_FEEL,
357 //								  B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
358 //		fConfigWindow->AddChild(view);
359 //		// Just to make sure
360 //		view->MoveTo(0, 0);
361 //		view->ResizeTo(rect.Width(), rect.Height());
362 //		view->ResizeToPreferred();
363 //		fConfigWindow->MoveTo(100, 100);
364 //		fConfigWindow->Show();
365 //	}
366 }
367 
368 // _BuildMenu
369 void
370 SavePanel::_BuildMenu()
371 {
372 	fFormatM = new BPopUpMenu("Format");
373 
374 	fNativeMI = new SaveItem("Icon-O-Matic", new BMessage(MSG_FORMAT),
375 							 EXPORT_MODE_MESSAGE);
376 	fFormatM->AddItem(fNativeMI);
377 	fNativeMI->SetEnabled(false);
378 
379 	fFormatM->AddSeparatorItem();
380 
381 	fHVIFMI = new SaveItem("HVIF", new BMessage(MSG_FORMAT),
382 						   EXPORT_MODE_FLAT_ICON);
383 	fFormatM->AddItem(fHVIFMI);
384 
385 	fRDefMI = new SaveItem("HVIF RDef", new BMessage(MSG_FORMAT),
386 						   EXPORT_MODE_ICON_RDEF);
387 	fFormatM->AddItem(fRDefMI);
388 
389 	fFormatM->AddSeparatorItem();
390 
391 	fSVGMI = new SaveItem("SVG", new BMessage(MSG_FORMAT),
392 						  EXPORT_MODE_SVG);
393 	fFormatM->AddItem(fSVGMI);
394 
395 	fFormatM->AddSeparatorItem();
396 
397 	fBitmapMI = new SaveItem("PNG", new BMessage(MSG_FORMAT),
398 							 EXPORT_MODE_BITMAP);
399 	fFormatM->AddItem(fBitmapMI);
400 
401 	fBitmapSetMI = new SaveItem("PNG Set", new BMessage(MSG_FORMAT),
402 								EXPORT_MODE_BITMAP_SET);
403 	fFormatM->AddItem(fBitmapSetMI);
404 
405 	fFormatM->AddSeparatorItem();
406 
407 	fIconAttrMI = new SaveItem("BEOS:ICON Attribute", new BMessage(MSG_FORMAT),
408 							   EXPORT_MODE_ICON_ATTR);
409 	fFormatM->AddItem(fIconAttrMI);
410 
411 	fIconMimeAttrMI = new SaveItem("META:ICON Attribute", new BMessage(MSG_FORMAT),
412 								   EXPORT_MODE_ICON_MIME_ATTR);
413 	fFormatM->AddItem(fIconMimeAttrMI);
414 
415 
416 	fFormatM->SetTargetForItems(this);
417 
418 	// pick the RDef item in the list
419 	fRDefMI->SetMarked(true);
420 }
421 
422 // _EnableSettings
423 void
424 SavePanel::_EnableSettings() const
425 {
426 	// no settings currently necessary
427 	fSettingsB->SetEnabled(false);
428 }
429 
430