/************************************************************************
						 ３Ｄ-ＣＡＤプログラム

						Programmed by Y.Nishida

												[ Oct.18, 1993 ]
 ************************************************************************/

#define unchar unsignedchar

#include <stdio.h>
#include "ToolBox.h"
#include "External.h"
#include "Prototype.h"

#define	DESIGN_WIDTH	1024
#define	DESIGN_HEIGHT	1024

#define	TOP_VIEW	0
#define	FRONT_VIEW	1
#define	RIGHT_VIEW	2
#define	PERS_VIEW	3

static WindowPtr toolWindow[2];			/* ツール・ウィンドウへのポインタ		*/
static WindowPtr designWindow[4];		/* デザイン・ウィンドウへのポインタ		*/
static DesignRecord designWinInfo[4];	/* デザイン・ウィンドウの情報			*/

/************************************************************************
	デザイン・ウィンドウのデフォルトの大きさを計算する.
 ************************************************************************/

static void SetDesignDefaultSize(window)
WindowPtr window;
{
	int sizex1 = (DESIGN_WIDTH +16);
	int sizey1 = (DESIGN_HEIGHT+16+20);
	int sizex2 = topLevel.window.width  - 20;
	int sizey2 = topLevel.window.height - 40;

	if (((DesignPtr)(window->refCon))->scrlLBar != NULL) sizex1 += 15;

	if (sizex1 > sizex2) sizex1 = sizex2;
	if (sizey1 > sizey2) sizey1 = sizey2;
	SetWindowStdSize(window,10,30,sizex1,sizey1);
}

/************************************************************************
	全てのデザイン・ウィンドウのデフォルト・サイズを設定する.
 ************************************************************************/

extern void ResetDesignWindowDefaultSize()
{
	int number;

	for (number=0; number<4; number++) {
		SetDesignDefaultSize(designWindow[number]);
	}
}

/************************************************************************
	ツール・ウィンドウを開ける.
 ************************************************************************/

static void OpenToolWindow(window)
WindowPtr window;
{
	int toolNumber = (int)GetWindowRefCon(window);

	ShowApplWindow(window);
	SetMenuMark(windowMenu,toolNumber+5,1);
}

/************************************************************************
	ツール・ウィンドウを閉じる.
 ************************************************************************/

static void CloseToolWindow(window)
WindowPtr window;
{
	int toolNumber = (int)GetWindowRefCon(window);

	HideApplWindow(window);
	SetMenuMark(windowMenu,toolNumber+5,0);
}

/************************************************************************
	メニューよりツール・ウィンドウを開け閉めする.
 ************************************************************************/

extern void ControlToolWindow(item)
MItemPtr item;
{
	WindowPtr window = toolWindow[GetItemRefCon(item)-6];
	int mark		 = GetItemMark(item);

	if (mark == 0)  OpenToolWindow(window);
			  else CloseToolWindow(window);
}

/************************************************************************
	デザイン・ウィンドウを開ける.
 ************************************************************************/

static void OpenDesignWindow(window)
WindowPtr window;
{
	DesignPtr design = (DesignPtr)GetWindowRefCon(window);

	ShowApplWindow(window);
	SetMenuMark(windowMenu,design->windowNo+1,1);
}

/************************************************************************
	デザイン・ウィンドウを閉じる.
 ************************************************************************/

static void CloseDesignWindow(window)
WindowPtr window;
{
	DesignPtr design = (DesignPtr)GetWindowRefCon(window);

	HideApplWindow(window);
	SetMenuMark(windowMenu,design->windowNo+1,0);
}

/************************************************************************
	メニューよりデザイン・ウィンドウを開け閉めする.
 ************************************************************************/

extern void ControlDesignWindow(item)
MItemPtr item;
{
	WindowPtr window = designWindow[GetItemRefCon(item)-1];
	int mark		 = GetItemMark(item);

	if (mark == 0)  OpenDesignWindow(window);
			  else CloseDesignWindow(window);
}

/************************************************************************
	背景スクリーンの初期化を行なう.
 ************************************************************************/

static void InitBackScreen(screen,scale)
Pixmap screen;
int scale;
{
	int pntx,pnty;
	int centerX = DESIGN_WIDTH  / 2;
	int centerY = DESIGN_HEIGHT / 2;

	XSetForeground(display,bitmapGPort,0);
	XFillRectangle(display,screen,bitmapGPort,0,0,DESIGN_WIDTH,DESIGN_HEIGHT);

	XSetForeground(display,bitmapGPort,1);
/*	XSetLineAttributes(display,bitmapGPort,1,LineOnOffDash,CapButt,JoinMiter);	*/

	for (pntx = 0; pntx < centerX; pntx += scale) {
		XDrawLine(display,screen,bitmapGPort,centerX+pntx,0,centerX+pntx,DESIGN_HEIGHT);
		XDrawLine(display,screen,bitmapGPort,centerX-pntx,0,centerX-pntx,DESIGN_WIDTH );
	}
	for (pnty = 0; pnty < centerY; pnty += scale) {
		XDrawLine(display,screen,bitmapGPort,0,centerY+pnty,DESIGN_WIDTH,centerY+pnty);
		XDrawLine(display,screen,bitmapGPort,0,centerY-pnty,DESIGN_WIDTH,centerY-pnty);
	}

	XSetLineAttributes(display,bitmapGPort,2,LineSolid,CapButt,JoinMiter);
	XDrawLine(display,screen,bitmapGPort,0,centerY,DESIGN_WIDTH,centerY);
	XDrawLine(display,screen,bitmapGPort,centerX,0,centerX,DESIGN_HEIGHT);

	XSetLineAttributes(display,bitmapGPort,1,LineSolid,CapButt,JoinMiter);
	XDrawRectangle(display,screen,bitmapGPort,0,0,DESIGN_WIDTH-1,DESIGN_HEIGHT-1);
}

/************************************************************************
	前景スクリーンの初期化を行なう.
 ************************************************************************/

static void InitForeScreen(screen,scale)
Pixmap screen;
int scale;
{
	int pntx,pnty;
	int centerX = DESIGN_WIDTH  / 2;
	int centerY = DESIGN_HEIGHT / 2;

	XSetForeground(display,bitmapGPort,0);
	XFillRectangle(display,screen,bitmapGPort,0,0,DESIGN_WIDTH,DESIGN_HEIGHT);

	XSetForeground(display,bitmapGPort,1);
	XDrawLine(display,screen,bitmapGPort,centerX+ 12,centerY-250,centerX+200,centerY- 30);
	XDrawLine(display,screen,bitmapGPort,centerX+200,centerY- 30,centerX-250,centerY+ 30);
	XDrawLine(display,screen,bitmapGPort,centerX-250,centerY+ 30,centerX+ 12,centerY-250);
}

/************************************************************************
	作業用スクリーンの初期化を行なう.
 ************************************************************************/

static void InitEditScreen(screen,scale)
Pixmap screen;
int scale;
{
	int pntx,pnty;
	int centerX = DESIGN_WIDTH  / 2;
	int centerY = DESIGN_HEIGHT / 2;

	XSetForeground(display,bitmapGPort,0);
	XFillRectangle(display,screen,bitmapGPort,0,0,DESIGN_WIDTH,DESIGN_HEIGHT);
	XSetForeground(display,bitmapGPort,1);
	XDrawLine(display,screen,bitmapGPort,centerX+ 12,centerY-150,centerX+100,centerY- 30);
}

/************************************************************************
	デザイン・ウィンドウのアップデート処理を行なう.
 ************************************************************************/

static void UpdateDesignWindow(event,wcore)
XEventPtr event;
WCorePtr wcore;
{
	ControlPtr ctrl  = (ControlPtr)wcore;
	DesignPtr design = (DesignPtr)ctrl->refCon;

	int desPx = event->xexpose.x;
	int desPy = event->xexpose.y;
	int sizeX = event->xexpose.width;
	int sizeY = event->xexpose.height;
	int souPx = desPx + design->homex;
	int souPy = desPy + design->homey;

	XSetPlaneMask(display,pixmapGPort,1);
	XCopyPlane(display,design->backScreen,wcore->windowID,pixmapGPort,souPx,souPy,sizeX,sizeY,desPx,desPy,1);
	XSetPlaneMask(display,pixmapGPort,2);
	XCopyPlane(display,design->foreScreen,wcore->windowID,pixmapGPort,souPx,souPy,sizeX,sizeY,desPx,desPy,1);
	XSetPlaneMask(display,pixmapGPort,4);
	XCopyPlane(display,design->editScreen,wcore->windowID,pixmapGPort,souPx,souPy,sizeX,sizeY,desPx,desPy,1);
}

/************************************************************************
	デザイン・ウィンドウのズーム・イン処理を行なう.
 ************************************************************************/

static void ZoomInDesignWindow(ctrl)
ControlPtr ctrl;
{
	DesignPtr design = (DesignPtr)ctrl->refCon;

	if (design->scale < 64) {
		design->scale *= 2;

		InitBackScreen(design->backScreen,design->scale);
		XClearArea(display,GetWindowID(design->contents),0,0,0,0,true);
	}
}

/************************************************************************
	デザイン・ウィンドウのズーム・アウト処理を行なう.
 ************************************************************************/

static void ZoomOutDesignWindow(ctrl)
ControlPtr ctrl;
{
	DesignPtr design = (DesignPtr)ctrl->refCon;

	if (design->scale > 2) {
		design->scale /= 2;

		InitBackScreen(design->backScreen,design->scale);
		XClearArea(display,GetWindowID(design->contents),0,0,0,0,true);
	}
}

/************************************************************************
	３Ｄビュー・ウィンドウのアップデート処理を行なう.
 ************************************************************************/

static void Update3DViewWindow(event,wcore)
XEventPtr event;
WCorePtr wcore;
{
	ControlPtr ctrl  = (ControlPtr)wcore;
	DesignPtr design = (DesignPtr)ctrl->refCon;

	int desPx = event->xexpose.x;
	int desPy = event->xexpose.y;
	int sizeX = event->xexpose.width;
	int sizeY = event->xexpose.height;
	int souPx = desPx + design->homex;
	int souPy = desPy + design->homey;

	XCopyPlane(display,design->backScreen,wcore->windowID,systemGPort,souPx,souPy,sizeX,sizeY,desPx,desPy,1);
}

/************************************************************************
	デザイン・ウィンドウへのイベントを処理する.
 ************************************************************************/

static void DesignEvent(event,wcore)
XEventPtr event;
WCorePtr wcore;
{
	switch (event->type) {
		case Expose: UpdateDesignWindow(event,wcore);	break;
	}
}

/************************************************************************
	ツールウィンドウを作成する.
 ************************************************************************/

static WindowPtr CreateToolWindow()
{
	int button;
	WindowPtr window = NewApplWindow(2,40,48,48*13+10,NULL,0x11,1,NULL);

	CreatePictSwitch(window,0,10,48,48,toolIcons[0],0,1,NULL);
	CreatePictSwitch(window,0,58,48,48,toolIcons[1],0,2,NULL);

	SetWindowCloseProc(window,CloseToolWindow);

	for (button=2; button<13; button++) {
		CreatePictButton(window,0,button*48+10,48,48,toolIcons[button],0,button+1,NULL);
	}
	return(window);
}

/************************************************************************
	デザイン・ウィンドウを作成する.
 ************************************************************************/

static WindowPtr CreateDesignWindow(number,px,py,width,height,name,design)
int number,px,py,width,height;
String name;
DesignPtr design;
{
	WindowPtr window = NewApplWindow(px,py,width,height,name,0x0f,(long)design,NULL);

	SetWindowGrowProc(window,AdjustDesignWindow);
	SetWindowZoomProc(window,AdjustDesignWindow);
	SetWindowCloseProc(window,CloseDesignWindow);

	design->backScreen = XCreatePixmap(display,mainWindow,DESIGN_WIDTH,DESIGN_HEIGHT,1);
	design->foreScreen = XCreatePixmap(display,mainWindow,DESIGN_WIDTH,DESIGN_HEIGHT,1);
	design->editScreen = XCreatePixmap(display,mainWindow,DESIGN_WIDTH,DESIGN_HEIGHT,1);

	design->contents = CreateSubWindow(window,-1,19,100,100,1,(long)design,DesignEvent);
	design->scrlHBar = CreateScrollBar(window, 0, 0,100, 15,0,100,0,(long)design,ScrollDesignWindow);
	design->scrlRBar = CreateScrollBar(window, 0, 0, 15,100,0,100,0,(long)design,ScrollDesignWindow);
	design->scrlLBar = NULL;

	design->zoomIn   = CreatePictButton(window,0,0,32,15,  scaleUpPict,1,(long)design,ZoomInDesignWindow);
	design->zoomOut  = CreatePictButton(window,0,0,32,15,scaleDownPict,1,(long)design,ZoomOutDesignWindow);

	design->windowNo  = number;
	design->window	  = window;
	design->homex	  = (DESIGN_WIDTH  - (width -16)) / 2;
	design->homey	  = (DESIGN_HEIGHT - (height-36)) / 2;
	design->width	  = DESIGN_WIDTH;
	design->height	  = DESIGN_HEIGHT;
	design->scale	  = 8;

	SetDesignDefaultSize(window);
	SetWindowSizeLimit(window,128,128,DESIGN_WIDTH+16+15,DESIGN_HEIGHT+16+20);
	AdjustDesignWindow(window);

	InitBackScreen(design->backScreen,design->scale);
	InitForeScreen(design->foreScreen,design->scale);
	InitEditScreen(design->editScreen,design->scale);

	XSelectInput(display,GetWindowID(design->contents),ExposureMask);

	return(window);
}

/************************************************************************
	３Ｄウィンドウを作成する.
 ************************************************************************/

static WindowPtr Create3DViewWindow(number,px,py,width,height,name,design)
int number,px,py,width,height;
String name;
DesignPtr design;
{
	WindowPtr window = NewApplWindow(px,py,width,height,name,0x0f,(long)design,NULL);

	SetWindowGrowProc(window,Adjust3DViewWindow);
	SetWindowZoomProc(window,Adjust3DViewWindow);
	SetWindowCloseProc(window,CloseDesignWindow);

	design->foreScreen = XCreatePixmap(display,mainWindow,DESIGN_WIDTH,DESIGN_HEIGHT,defaultDepth);

	design->contents = CreateSubWindow(window,15,19,100,100,1,(long)design,NULL);
	design->scrlHBar = CreateScrollBar(window, 0, 0,100, 15,0,100,0,(long)design,NULL);
	design->scrlRBar = CreateScrollBar(window, 0,19, 15,100,0,100,0,(long)design,NULL);
	design->scrlLBar = CreateScrollBar(window,-1,19, 15,100,0,100,0,(long)design,NULL);

	design->zoomIn   = CreatePictButton(window,0,0,32,15,  scaleUpPict,1,0,NULL);
	design->zoomOut  = CreatePictButton(window,0,0,32,15,scaleDownPict,1,0,NULL);

	design->windowNo  = number;
	design->window	  = window;
	design->homex	  = (DESIGN_WIDTH  - (width -16)) / 2;
	design->homey	  = (DESIGN_HEIGHT - (height-36)) / 2;
	design->width	  = DESIGN_WIDTH;
	design->height	  = DESIGN_HEIGHT;

	SetDesignDefaultSize(window);
	SetWindowSizeLimit(window,128,128,DESIGN_WIDTH+16+15,DESIGN_HEIGHT+16+20);
	Adjust3DViewWindow(window);
	XSelectInput(display,GetWindowID(design->contents),ExposureMask);

	return(window);
}

/************************************************************************
	アプリケーション・ウィンドウの初期化を行なう.
 ************************************************************************/

extern void InitWindows()
{
	int count;

	toolWindow[0]			 = CreateToolWindow();
	designWindow[  TOP_VIEW] = CreateDesignWindow(  TOP_VIEW, 60, 40,460,320," Top "	 ,&designWinInfo[  TOP_VIEW]);
	designWindow[FRONT_VIEW] = CreateDesignWindow(FRONT_VIEW, 60,370,460,320," Front "	 ,&designWinInfo[FRONT_VIEW]);
	designWindow[RIGHT_VIEW] = CreateDesignWindow(RIGHT_VIEW,530,370,460,320," Right "	 ,&designWinInfo[RIGHT_VIEW]);
	designWindow[ PERS_VIEW] = Create3DViewWindow( PERS_VIEW,530, 40,460,320," 3D View " ,&designWinInfo[ PERS_VIEW]);

	ShowApplWindow(toolWindow[0]);
	for (count=0; count<4; count++) ShowApplWindow(designWindow[count]);
}

/************************************************************************
	デザイン・ウィンドウの整理を行なう.
 ************************************************************************/

extern void CleanUpDesignWindows(item)
MItemPtr item;
{
	int width  = (topLevel.window.width  - 80) / 2;
	int height = (topLevel.window.height - 60) / 2;

	MoveApplWindow(toolWindow[0],2,40);

	MoveApplWindow(designWindow[0],	  60,	 40);
	GrowApplWindow(designWindow[0],width,height);
	AdjustDesignWindow(designWindow[0]);

	MoveApplWindow(designWindow[1],	  60,height+50);
	GrowApplWindow(designWindow[1],width,height	  );
	AdjustDesignWindow(designWindow[1]);

	MoveApplWindow(designWindow[2],width+70,height+50);
	GrowApplWindow(designWindow[2],width   ,height	 );
	AdjustDesignWindow(designWindow[2]);

	MoveApplWindow(designWindow[3],width+70,	40);
	GrowApplWindow(designWindow[3],width   ,height);
	Adjust3DViewWindow(designWindow[3]);
}

