/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	DIBitmapViewer.cpp
 *
 *****************************************************************************/


// SOL++2000 
// 2000.02.18


#include <sol\MdiFrame.h>
#include <sol\MdiChild.h>
#include <sol\PaintDC.h>
#include <sol\FileDialog.h>
#include <sol\Dibitmap.h>
#include <sol\ClientDC.h>
#include <sol\DIBitmapFile.h>
#include "resource.h"


// class MdiDIBitmap
class MdiDIBitmap :public MdiChild {
	BOOL	alive;
	DIBitmap*	bitmap;
	void	redraw();
	long	paint(Event& event);
	long	close(Event& event);
	long	mdiActivate(Event& event);

  public:
	MdiDIBitmap(MdiClient* parent, const char* caption, Args& args);
	~MdiDIBitmap() {
		if(bitmap) delete bitmap;
	}

	void	load(char* filename);
	BOOL	isAlive() { return alive; }
	long	queryNewPalette(Event& event);
};


long	MdiDIBitmap::paint(Event& event)
{
	PaintDC pdc(this);
	if(bitmap) {
		int x = getScrollPos(HORIZONTAL);
		int y = getScrollPos(VERTICAL);
		bitmap -> setSource(x, y);
		bitmap -> draw(pdc, 0, 0);
	}
	return 0L;
}


long	MdiDIBitmap::close(Event& event)
{
	char title[256];
	getText(title, sizeof(title));
	int rc = MessageBox(getWindow(), 
			"This will close MdiDIBitmap Window.", 
			title, MB_OKCANCEL);
	if(rc == IDOK) {
		defaultProc(event);
		if(bitmap) delete bitmap;
		bitmap = NULL;
		alive  = FALSE;
		return TRUE;
	}
	return FALSE;
}


MdiDIBitmap::MdiDIBitmap(MdiClient* parent, const char* caption, Args& args)
	:MdiChild(parent, caption, 
		args.set(XmNstyle, 
			(ulong)WS_VISIBLE|WS_CHILD|WS_VSCROLL|WS_HSCROLL))
{
	alive  = TRUE;
	bitmap = NULL;
	addEventHandler(WM_PAINT, this,
		(Handler)&MdiDIBitmap::paint, NULL);
	addEventHandler(WM_CLOSE, this,
		(Handler)&MdiDIBitmap::close, NULL);
	addEventHandler(WM_QUERYNEWPALETTE, this,
		(Handler)&MdiDIBitmap::queryNewPalette, NULL);

}

long MdiDIBitmap::queryNewPalette(Event& event)
{
	redraw();
	return 0L;
}

void MdiDIBitmap::redraw()
{
	if(bitmap) {
		int w, h;
		bitmap -> getSize(w, h);
		setScrollExtent(w, h);

		Palette* pal = bitmap -> getPalette();
		if(pal) {
			ClientDC cdc(this);
			HPALETTE hpal = cdc.select(pal, FALSE);
			int num = cdc.realizePalette();
			cdc.select(hpal, FALSE);
			cdc.realizePalette();
			if(num >0) {
	   			update();
			}
		}
	}
}


long MdiDIBitmap::mdiActivate(Event& event)
{
	MdiChild::mdiActivate(event);
	redraw();

	MdiFrame* frame =getMdiFrame();
 	frame -> childActivated(this);
	return 0L;
}


void	MdiDIBitmap::load(char* filename)
{
	DIBitmapFile file;

	if(file.openReadOnly(filename) == TRUE) {
		DIBitmap* tbitmap = file.extract();
		file.close();
	    if(tbitmap) {
			if(bitmap) delete bitmap;
			bitmap = tbitmap;

			setScrollPos(VERTICAL, 0);
			setScrollPos(HORIZONTAL, 0);
			redraw();
		}
	}
}


// class DIBitmapViewer
class DIBitmapViewer :public MdiFrame {
	int	    max;
	int	    num;
	MdiDIBitmap**  images;
	FileDialog filedlg;
	void	open(Action& action);
	long	close(Event& event);
	long	paletteChanged(Event& event);
  public:
	DIBitmapViewer(Application& applet, const char* caption, Args& args);
	~DIBitmapViewer();
	void	childActivated(View* view);
};


DIBitmapViewer::DIBitmapViewer(Application& applet, const char* caption, Args& args)
	:MdiFrame(applet, caption, args)
{
	addCallback(XmNmenuCallback, ID_OPEN, this, 
		(Callback)&DIBitmapViewer::open, NULL);
	addCallback(XmNmenuCallback, ID_EXIT, this, 
		(Callback)&DIBitmapViewer::exit, NULL);

	addCallback(XmNmenuCallback, ID_TILE, this, 
		(Callback)&DIBitmapViewer::tile, NULL);
	addCallback(XmNmenuCallback, ID_CASCADE, this, 
		(Callback)&DIBitmapViewer::cascade, NULL);
	addCallback(XmNmenuCallback, ID_ICONARRANGE, this, 
		(Callback)&DIBitmapViewer::iconArrange, NULL);
	addEventHandler(WM_CLOSE, this,
		(Handler)&DIBitmapViewer::close, NULL);

	max = 100;
	num = 0;
	images = new MdiDIBitmap*[max];
	for(int i = 0; i<max; i++) 
		images[i] = NULL;

	char dir[128];
	::GetWindowsDirectory(dir, sizeof(dir));
	Args ar;
	ar.set(XmNdirectory, (ulong)dir);
	ar.set(XmNfilter, "Bitmap (*.bmp)\0 *.bmp\0");
	filedlg.create(this, NULL, ar);
}


DIBitmapViewer::~DIBitmapViewer()
{
	for(int i = 0; i<num; i++) {
		if(images[i]) delete images[i];
	}
}


long DIBitmapViewer::paletteChanged(Event& event)
{
	HWND hwnd =	(HWND)event.getWParam();
	if(hwnd != getWindow()) {
		return ::SendMessage(hwnd, WM_QUERYNEWPALETTE,
			event.getWParam(), event.getLParam());
	}	
	else 
		return 0L;
}

void DIBitmapViewer::childActivated(View* view)
{
	MdiDIBitmap* sender = (MdiDIBitmap*)view;
	
	for(int i = 0; i<num; i++) {
		if(images[i] && images[i]!=sender) {
  			images[i]->update();
		}
	}
}

long DIBitmapViewer::close(Event& event)
{
	int flag = TRUE;
	for(int i = 0; i<num; i++) {
		if(images[i] && images[i]->isAlive()) {
			int rc = (int)images[i]->send(WM_CLOSE, 0, 0L);
			if (rc == TRUE) {
				delete images[i];
				images[i] = NULL;
			}
			else flag = FALSE;
		}
	}
	if(flag) {
		num = 0;
		return defaultProc(event);
	}
	else
		return NULL;
}


void DIBitmapViewer::open(Action& action)
{
	if(filedlg.open() && num < max) {
		int n = num;
		for(int i = 0; i<num; i++) {
			if(images[i] && 
			   images[i]->isAlive() == FALSE) {
				delete images[i];
				images[i] = NULL;
			}
			if(images[i] == NULL) {
				n = i;
				break;
			}
		}
		char* filename = filedlg.getFileName();
		MdiClient* mdiClient = getClient();
		Args ar;
		ar.set(XmNx,     (int)CW_USEDEFAULT);
		ar.set(XmNy,     (int)CW_USEDEFAULT);
		ar.set(XmNwidth, (int)CW_USEDEFAULT);
		ar.set(XmNheight,(int)CW_USEDEFAULT);
		ar.set(XmNmenuId, 1);
		ar.set(XmNmenuName, "ImageChild");
		images[n] = new MdiDIBitmap(mdiClient, "MdiDIBitmap", ar);
		images[n] -> setText(filename);

		images[n] -> load(filename);

		if(n == num) num++;
		for(int j = 0; j<num; j++) {
			if(images[j]) {
				images[j]->update();
			}
		}
	}
}


void	Main(int argc, char** argv)
{
	const char* appClass = "DIBitmapViewer";
	Application applet(appClass, argc, argv);

	Args args;
	args.set(XmNchildId, 100);
	args.set(XmNmenuId,    0);
	args.set(XmNmenuName, appClass);
	DIBitmapViewer DIBitmapViewer(applet, appClass, args);
	DIBitmapViewer.realize();

	applet.run();
}
