// Ce code source des exemples MFC illustre l'utilisation de l'interface utilisateur Microsoft Office Fluent MFC 
// (interface utilisateur "Fluent UI"). Il est fourni uniquement en tant que référence complémentaire du 
// Guide de référence Microsoft Foundation Classes et de la documentation électronique associée 
// inclus avec les logiciels de la bibliothèque MFC C++.  
// Les termes du contrat de licence pour la copie, l'utilisation ou la distribution de l'interface utilisateur Fluent sont disponibles séparément.  
// Pour en savoir plus sur notre programme de licence de l'interface utilisateur Fluent, visitez 
// http://msdn.microsoft.com/officeui.
//
// Copyright (C) Microsoft Corporation
// Tous droits réservés.

// GrapheurView.cpp : implémentation de la classe CGrapheurView
//

#include "stdafx.h"
// SHARED_HANDLERS peuvent être définis dans les gestionnaires d'aperçu, de miniature
// et de recherche d'implémentation de projet ATL et permettent la partage de code de document avec ce projet.
#ifndef SHARED_HANDLERS
#include "Grapheur.h"
#endif

#include "GrapheurDoc.h"
#include "GrapheurView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#include <math.h>

// CGrapheurView

IMPLEMENT_DYNCREATE(CGrapheurView, CView)

BEGIN_MESSAGE_MAP(CGrapheurView, CView)
	// Commandes d'impression standard
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CGrapheurView::OnFilePrintPreview)
	ON_WM_CONTEXTMENU()
	ON_WM_RBUTTONUP()
END_MESSAGE_MAP()

// construction ou destruction de CGrapheurView

CGrapheurView::CGrapheurView()
{
	// TODO: ajoutez ici du code de construction

}

CGrapheurView::~CGrapheurView()
{
}

BOOL CGrapheurView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: changez ici la classe ou les styles Window en modifiant
	//  CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

// dessin de CGrapheurView

void CGrapheurView::OnDraw(CDC* pDC)
{
	CGrapheurDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: ajoutez ici le code de dessin pour les données natives
	// associer la palette au DC
	CPalette* pOldPal;		// ancienne
	pOldPal = pDC->SelectPalette(&m_Palette, true);
	pDC->RealizePalette() ;

	// MX et MY déterminent la qualité de l'image
	int MX,MY;
	MX = 1500;
	MY = 1500;

	// dimensionner l'écran
	RECT rc;
	GetClientRect(&rc);

	// changer de repère et de système de coordonnées
	if(!pDC->IsPrinting()) {
		// dessiner une image de fond
		CBrush brosse;
		CBitmap image;
		/*image.LoadBitmap(IDB_IMAGE);
		brosse.CreatePatternBrush(&image);
		pDC->FillRect(&rc,&brosse);
*/
		pDC->SetMapMode(MM_ISOTROPIC);
		pDC->SetViewportExt(rc.right,-rc.bottom);	// rapport de coordonnées
		pDC->SetViewportOrg(rc.right/2,rc.bottom/2);// fixer l'origine
	}
	pDC->SetWindowExt(2*MX,2*MY);				// plan de 1500² points

	CRect zone_invalide;	// zone à rafraîchir
	CPoint test;		// un point
	pDC->GetClipBox(&zone_invalide);
	zone_invalide.NormalizeRect();

	// créer une police
	police=new CFont;
	police->CreatePointFont(14*10,(LPCTSTR)"Arial",pDC);
	pDC->SelectObject(police);

	CRect pos;
	CSize ttexte;
	char msg[500];
	sprintf(msg,"Graphique vu en 3D, %dx%d points",MX,MY);
	CString cmsg((char*)msg);
	ttexte=pDC->GetTextExtent(cmsg);

	pos.left=-(ttexte.cx)/2;
	pos.right=pos.left+ttexte.cx;

	pos.top=-MX*0.75;
	pos.bottom=-MX;

	if(!pDC->IsPrinting())
	{
		pDC->SetBkMode(TRANSPARENT);

		pDC->SetTextColor(RGB(248,172,122));
		pDC->DrawText(cmsg,&pos,0);

		int dec = 15;
		pos.left += dec;
		pos.top -= dec;
		pos.right += dec;

		pDC->SetTextColor(RGB(250,234,96));
		pDC->DrawText(cmsg,&pos,0);
	} else {
		pDC->SetTextColor(RGB(0,0,0));
		pDC->DrawText(cmsg,&pos,0);
	}




	// -----------------------------------------------------
	// vue en 3D
	double a1,a2,a3,b1,b2,b3;	// coefficients de projection 3D
	double l,L;					// lattitude et longitude

	// point de vue
	l=1.1;
	L=1.20;

	// ces coofficients sont calculés pour une projection orthogonale
	a1 = -sin(L);
	a2 = cos(L);
	a3 = 0;
	b1 = -sin(l)*cos(L);
	b2 = -sin(l)*cos(L);
	b3 = cos(l);

	// -----------------------------------------------------	
	int i,j;	// coordonnées dans l'espace logique	
	int X,Y;	// coordonnées projetées (X,Y)=proj(x,y,z)
	
	int coul;		// couleur des points
	double cote;
	double x,y;

	for(i=-MX;i<MX;i++)
		for(j=-MY;j<MY;j++)
		{											
			x = (double)i/MX*2;
			y = (double)j/MY*2;
			cote = 100 * sin(x)*sin(y)*exp(x*x - x*y +y*y);
			
			coul = 1000 + cote;

			if(coul>4000)
				coul = 3500 - rand();

			if(coul<0)
				coul = 800 + rand();

			// projection sur un plan
			X= a1*i + a2*j + a3*cote;
			Y= b1*i + b2*j + b3*cote;

			test.x = X;
			test.y = Y;

			if(PtInRect(&zone_invalide,test)) // le point est-il invalide ?
				pDC->SetPixel(test,PALETTEINDEX(coul)); // 40*100=4000
			
		}

	// ----------------------------------------------------------------
	// libérer GDI
	pDC->SelectPalette( pOldPal,true ) ;
	m_Palette.DeleteObject() ;
	pDC->SelectStockObject(ANSI_VAR_FONT);
	delete police;

}


// impression de CGrapheurView
void CGrapheurView::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
	AFXPrintPreview(this);
#endif
}

BOOL CGrapheurView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// préparation par défaut
	return DoPreparePrinting(pInfo);
}

void CGrapheurView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: ajoutez une initialisation supplémentaire avant l'impression
}

void CGrapheurView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: ajoutez un nettoyage après l'impression
}

void CGrapheurView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
	ClientToScreen(&point);
	OnContextMenu(this, point);
}

void CGrapheurView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}


// diagnostics pour CGrapheurView

#ifdef _DEBUG
void CGrapheurView::AssertValid() const
{
	CView::AssertValid();
}

void CGrapheurView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CGrapheurDoc* CGrapheurView::GetDocument() const // la version non Debug est inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CGrapheurDoc)));
	return (CGrapheurDoc*)m_pDocument;
}
#endif //_DEBUG


// gestionnaires de messages pour CGrapheurView
void CGrapheurView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
	
	// préparer une palette personnalisée
	nColors = 4000;		// nombre de couleurs représentées dans la palette

	// réserver la mémoire pour exprimer la palette
	m_pPalette = (LOGPALETTE*)new char[sizeof(LOGPALETTE) +
		sizeof(PALETTEENTRY)*nColors];

	// définir les nuances de la palette
	m_pPalette->palVersion = 0x300;
	m_pPalette->palNumEntries = nColors ;

	for( int co=0 ; co<192 ; co++) {
		m_pPalette->palPalEntry[co].peRed = 0;
		m_pPalette->palPalEntry[co].peBlue = co;
		m_pPalette->palPalEntry[co].peGreen = co >> 4;
		m_pPalette->palPalEntry[co].peFlags = 0;
	}

	for( int co = 192 ; co<256 ; co++) {
		m_pPalette->palPalEntry[co].peRed = 0;
		m_pPalette->palPalEntry[co].peBlue = co;
		m_pPalette->palPalEntry[co].peGreen = co;
		m_pPalette->palPalEntry[co].peFlags = 0;
	}

	for( int co = 256 ; co<nColors ; co++) {
		m_pPalette->palPalEntry[co].peRed = co >> 3;
		m_pPalette->palPalEntry[co].peBlue = co >> 4;
		m_pPalette->palPalEntry[co].peGreen = co >> 2;
		m_pPalette->palPalEntry[co].peFlags = 0;
	}

	// créer la palette dans GDI
	m_Palette.CreatePalette( m_pPalette ) ;
	m_Palette.SetPaletteEntries( 0, nColors,
					(PALETTEENTRY*)&m_pPalette->palPalEntry ) ;

	CView::OnPrepareDC(pDC, pInfo);
}