/*
**	Copyright 2000 Be Incorporated. All Rights Reserved.
**	This file may be used under the terms of the Be Sample Code 
**	License.
*/

#include <Window.h>
#include <File.h>
#include <String.h>

#include <stdio.h>

#include "main.h"
#include "CadWindow.h"
#include "ToolBar.h"

CadWindow::CadWindow():
	BWindow(BRect(50, 50, 640, 480), "BeCAD", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS),
	fSavePanel(NULL),
	fOpenPanel(NULL)
	
{
	// build/intialize user interface
	BRect	winRect = Bounds();
	// build/initialize the menubar
	winRect.top += BuildMenuBar(winRect) + 1;

	// build/initialize the views
	BView	*toolBar;
	toolBar = new ToolBar(winRect, "tool bar");
	AddChild(toolBar);
	winRect.top += toolBar->Bounds().Height() + 1;
	
	fCadView = new CadPictureView(winRect, "Main Cad View");
	AddChild(fCadView);

	//Here are some initial defaults:
	fCadView->SetGraphState(true);
	fMenuBarOptionsGrid->SetMarked(true);
}

/***********************/

float CadWindow::BuildMenuBar(BRect winRect)
{
	// build menubar
	fMenuBar 	       = new BMenuBar(winRect, "menu bar");
	
		// build File menu
	BMenu	*menuBarFile;
	menuBarFile      = new BMenu("File");

	fMenuBar->AddItem(menuBarFile);
	menuBarFile->AddItem(new BMenuItem("About", new BMessage(MENU_FILE_ABOUT)) );
	menuBarFile->AddSeparatorItem();
	menuBarFile->AddItem(new BMenuItem("Open", new BMessage(MENU_FILE_OPEN), 'O' ));
	menuBarFile->AddItem(new BMenuItem("Save", new BMessage(MENU_FILE_SAVE), 'S' ));
	menuBarFile->AddItem(new BMenuItem("Save As...", new BMessage(MENU_FILE_SAVEAS), 'S', B_SHIFT_KEY ));
	menuBarFile->AddItem(new BMenuItem("Exit", new BMessage(B_QUIT_REQUESTED), 'Q' ));

	fMenuBarOptions = new BMenu("Options");
	fMenuBarOptionsGrid = new BMenuItem("Grid", new BMessage(MENU_OPTIONS_GRID));
	
	fMenuBar->AddItem(fMenuBarOptions);
	fMenuBarOptions->AddItem(fMenuBarOptionsGrid);
	fMenuBarOptions->AddItem(new BMenuItem("10 unit grid", new BMessage(M10_UNIT_GRID)));
	fMenuBarOptions->AddItem(new BMenuItem("20 unit grid", new BMessage(M20_UNIT_GRID)));
	fMenuBarOptions->AddItem(new BMenuItem("40 unit grid", new BMessage(M40_UNIT_GRID)));	
		
	AddChild(fMenuBar);
	return(fMenuBar->Bounds().Height());
}

/***********************/

void CadWindow::MessageReceived(BMessage *msg)
{
	switch (msg->what) {
	
	case MENU_FILE_ABOUT: {
		BAlert *alert;
		alert = new BAlert("", "Everybody needs an About Box.", 
						"Neat, Huh?", NULL, NULL, B_WIDTH_FROM_WIDEST, B_IDEA_ALERT);
		alert->Go();
		break;
	}


	/* Note: the following construction, involving the careful positioning of */
	/* three case clauses in a switch statement such that they loop through   */
	/* each other properly should probably be done in a much clearer and      */
	/* easier to understand way.  However, I find it neat, and every release  */
	/* of Be source code should contain at least one head-scratcher.  You've  */
	/* found it.   -- Adam                                                    */
	
	case MENU_SAVEPANEL_INVOKE: {
		BString filepath;
		entry_ref	ent;
		msg->FindRef("directory", &ent);
		
		BEntry tEntry(&ent);
		BPath tPath;
		tEntry.GetPath(&tPath);

		filepath << tPath.Path();
		
		BString leaf;
		msg->FindString("name", &leaf);
		
		filepath << "/" << leaf;
		
		fCadView->SetFileName(filepath.String());
		/** **NOTE** We fall through to the below case!! **/
	}
	
	case MENU_FILE_SAVE: {
		if (0 != strlen(fCadView->GetFileName())) {
			fCadView->Save(fCadView->GetFileName());
			break;
		}
		/** **NOTE** We fall through to the below case!! **/
	}
	
	case MENU_FILE_SAVEAS: {
		if(!fSavePanel) {
			fSavePanel = new BFilePanel(B_SAVE_PANEL);
			fSavePanel->SetTarget(BMessenger(this));
			fSavePanel->SetMessage(new BMessage(MENU_SAVEPANEL_INVOKE));
		}
		fSavePanel->Show();
		break;
	}

	case MENU_OPENPANEL_INVOKE: {

		BString filepath;
		entry_ref	ent;
		msg->FindRef("refs", &ent);
		
		BEntry tEntry(&ent);
		BPath tPath;
		tEntry.GetPath(&tPath);

		filepath << tPath.Path();
		BFile *inputFile = new BFile(filepath.String(), B_READ_ONLY);
		if(inputFile->InitCheck() == B_NO_ERROR) {
			BMessage *viewArchive = new BMessage;
			viewArchive->Unflatten(inputFile);		
				
			BRect vBounds = fCadView->Bounds();
			RemoveChild(fCadView);
			delete(fCadView);
			fCadView = new CadPictureView(viewArchive);
			fCadView->ResizeTo(vBounds.Width(), vBounds.Height());
			AddChild(fCadView);
			
			fMenuBarOptionsGrid->SetMarked(fCadView->GetGraphState());
			fCadView->Invalidate();
			fCadView->SetFileName(filepath.String());
		
			delete viewArchive;
		} else {
			printf("Couldn't open the file\n:");
		}
		
		delete inputFile;
		break;
	}
	
	case MENU_FILE_OPEN: {
		if(!fOpenPanel) {
			fOpenPanel = new BFilePanel(B_OPEN_PANEL);
			fOpenPanel->SetTarget(BMessenger(this));
			fOpenPanel->SetMessage(new BMessage(MENU_OPENPANEL_INVOKE));
		}
		fOpenPanel->Show();
		break;
	}
	
	case MENU_OPTIONS_GRID: {
		if(fMenuBarOptionsGrid->IsMarked() == false) {
			fCadView->SetGraphState(true);
			fMenuBarOptionsGrid->SetMarked(true);
		} else {
			fCadView->SetGraphState(false);
			fMenuBarOptionsGrid->SetMarked(false);
		}
		break;
	}
	
	case M10_UNIT_GRID: {
		fCadView->SetGridSize(10);
		break;
	}
	
	case M20_UNIT_GRID: {
		fCadView->SetGridSize(20);
		break;
	}
	
	case M40_UNIT_GRID: {
		fCadView->SetGridSize(40);
		break;
	}
	
	default: {
		BWindow::MessageReceived(msg);
		break;
	}

	} // end case
}

/***********************/

bool CadWindow::QuitRequested()
{
	if(fSavePanel) {
		delete fSavePanel;
	}
	
	if(fOpenPanel) {
		delete fOpenPanel;
	}

	be_app->PostMessage(B_QUIT_REQUESTED);
	return true;
}

