/* * MandelVroom 2.0 * * (c) Copyright 1987,1989 Kevin L. Clague, San Jose, CA * * All rights reserved. * * Permission is hereby granted to distribute this program's source * executable, and documentation for non-comercial purposes, so long as the * copyright notices are not removed from the sources, executable or * documentation. This program may not be distributed for a profit without * the express written consent of the author Kevin L. Clague. * * This program is not in the public domain. * * Fred Fish is expressly granted permission to distribute this program's * source and executable as part of the "Fred Fish freely redistributable * Amiga software library." * * Permission is expressly granted for this program and it's source to be * distributed as part of the Amicus Amiga software disks, and the * First Amiga User Group's Hot Mix disks. * * contents: this file contains the functions to handle MandelVroom's * Zoom box which is used for navigation around in the complex plane. */ #include "mandp.h" SHORT BoxSizeX = 3, BoxSizeY = 3, DragSize = 3; static SHORT HotSpotX, HotSpotY; struct Picture *ZoomedPict; #define MENUCODE(m,i,s) (SHIFTMENU(m)|SHIFTITEM(i)|SHIFTSUB(s)) /* * Picture (project) related commands */ ZoomInCmd(Msg) struct IntuiMessage *Msg; { struct Picture *Pict; Pict = (struct Picture *) Msg->IDCMPWindow->UserData; switch( Msg->Class ) { case GADGETDOWN: ZoomedPict = Pict; case MENUPICK: Pict->ZoomType = ZOOMIN; if ( ! (Pict->Flags & SCROLL_HAPPENED)) { CloseZoomBox(Pict); SetToPointer(); State = ZOOMINSTATE; } break; case MOUSEBUTTONS: if (Msg->Code == SELECTDOWN) { if (ZoomedPict->pNode.ln_Type == Pict->pNode.ln_Type) { StartZoomBox(ZoomedPict, Pict); ResizeZoomCmd(Msg); /* Pass control off to resize routine */ } } break; } } /* * StartZoomOut */ ZoomOutCmd( Msg ) struct IntuiMessage *Msg; { register struct Picture *Pict; if (Msg->Class == MENUPICK) { Pict = CurPict; } else { Pict = (struct Picture *) Msg->IDCMPWindow->UserData; } Pict->ZoomType = ZOOMOUT; AddHead( &Pict->zList, &Pict->zNode ); Pict->Flags |= ZOOM_BOX_OPEN; Pict->DrawPict = Pict; Pict->NavLeft = Pict->LeftMarg; Pict->NavRight = Pict->CountX + Pict->NavLeft - 1; Pict->NavTop = Pict->TopMarg; Pict->NavBot = Pict->CountY + Pict->NavTop - 1; ZoomOnOff( Pict ); } ResizeZoomCmd(Msg) struct IntuiMessage *Msg; { struct Window *Window; struct Picture *Pict; Window = Msg->IDCMPWindow; Pict = (struct Picture *) Window->UserData; switch( Msg->Class ) { case MOUSEBUTTONS: switch (Msg->Code) { case SELECTDOWN: if (State != ZOOMINSTATE) ZoomExtras(ZoomedPict); AllocLensTemp( ZoomedPict ); ModifyIDCMP(Window, Window->IDCMPFlags | MOUSEMOVE); State = RESIZEZOOMSTATE; break; case SELECTUP: ModifyIDCMP(Window, Window->IDCMPFlags & ~MOUSEMOVE); FreeLensTemp(); FinishResize(ZoomedPict); State = IDLESTATE; break; } break; case MOUSEMOVE: StretchZoomBox( ZoomedPict ); break; } } ZoomDragCmd(Msg) struct IntuiMessage *Msg; { struct Window *Window; struct Picture *Pict; Window = Msg->IDCMPWindow; Pict = (struct Picture *) Window->UserData; switch( Msg->Class ) { case MOUSEBUTTONS: ZoomExtras( ZoomedPict ); /* draw/undraw the extras */ switch( Msg->Code ) { case SELECTDOWN: /* start drag */ AllocLensTemp( ZoomedPict ); ModifyIDCMP(Window, Window->IDCMPFlags | MOUSEMOVE); State = ZOOMDRAGSTATE; break; case SELECTUP: /* stop slide */ FreeLensTemp(); ModifyIDCMP(Window, Window->IDCMPFlags & ~MOUSEMOVE); State = IDLESTATE; break; } break; case MOUSEMOVE: DragZoomBox( ZoomedPict ); Lens( ZoomedPict ); break; } } PropResizeCmd(Msg) struct IntuiMessage *Msg; { struct Window *Window; struct Picture *Pict; Window = Msg->IDCMPWindow; Pict = (struct Picture *) Window->UserData; switch( Msg->Class ) { case MOUSEBUTTONS: ZoomExtras( ZoomedPict ); /* draw/undraw the extras */ switch( Msg->Code ) { case SELECTDOWN: /* start resize */ AllocLensTemp( ZoomedPict ); StartPropStrech( ZoomedPict ); ModifyIDCMP(Window, Window->IDCMPFlags | MOUSEMOVE); State = PROPRESIZESTATE; break; case SELECTUP: /* stop resize */ FreeLensTemp(); ModifyIDCMP(Window, Window->IDCMPFlags & ~MOUSEMOVE); State = IDLESTATE; break; } break; case MOUSEMOVE: PropStretchBox( ZoomedPict ); Lens( ZoomedPict ); break; } } SetJuliaCmd(Msg) struct IntuiMessage *Msg; { switch( Msg->Class ) { case MENUPICK: SetToPointer(); ZoomedPict = CurPict; State = SETJULIASTATE; break; case GADGETDOWN: SetToPointer(); ZoomedPict = (struct Picture *) Msg->IDCMPWindow->UserData; State = SETJULIASTATE; break; case MOUSEBUTTONS: if (Msg->Code == SELECTDOWN) { SetJuliaPt(ZoomedPict, (struct Picture *) Msg->IDCMPWindow->UserData); State = IDLESTATE; } break; } } QueryHeightCmd(Msg) struct IntuiMessage *Msg; { struct Window *Window; struct Picture *Pict; Window = Msg->IDCMPWindow; Pict = (struct Picture *) Window->UserData; if (Pict->Flags & SCROLL_HAPPENED) return; switch( Msg->Class ) { case MOUSEBUTTONS: switch( Msg->Code ) { /* start query */ case SELECTDOWN: if (Pict->Counts && !(Pict->Flags & NO_RAM_GENERATE)) { ShowContour( MouseX, MouseY, 1 ); ModifyIDCMP(Window, Window->IDCMPFlags | MOUSEMOVE); State = QUERYHEIGHTSTATE; } break; case SELECTUP: /* stop query */ ModifyIDCMP(Window, Window->IDCMPFlags & ~MOUSEMOVE); State = IDLESTATE; break; } break; case MOUSEMOVE: ShowContour( MouseX, MouseY, 0); break; } } static int OldHeight; /* used to detect title change */ ShowContour(MouseX,MouseY,Flag) register int MouseX,MouseY; register int Flag; { register struct Picture *Pict; static char ScreenTitle[80]; int Height; float r, i; Pict = (struct Picture *) CurWind->UserData; if (Pict == NULL) return; if (MouseX >= Pict->LeftMarg && MouseY >= Pict->TopMarg && MouseX < CurWind->Width - Pict->RightMarg && MouseY < CurWind->Height - Pict->BotMarg) { Height = HeightPicked(Pict,MouseX,MouseY); r = Pict->RealLow + (MouseX - Pict->LeftMarg) * Pict->RealGap; i = Pict->ImagLow + (MouseY - Pict->TopMarg) * Pict->ImagGap; sprintf(ScreenTitle,"Height %3d r %f i %f", Height, r, i); SetWindowTitles( CurWind, (long) -1, ScreenTitle ); } } /* * Start Zoom box */ StartZoomBox( NavPict, DrawPict ) register struct Picture *NavPict; register struct Picture *DrawPict; { register struct Window *Window = DrawPict->Window; CloseZoomBox( NavPict); AddHead( &DrawPict->zList, &NavPict->zNode ); NavPict->Flags |= ZOOM_BOX_OPEN; NavPict->DrawPict = DrawPict; /* Draw first box */ NavPict->NavTop = NavPict->NavBot = MouseY; NavPict->NavLeft = NavPict->NavRight = MouseX; ZoomBox( NavPict ); } StretchZoomBox( Pict ) register struct Picture *Pict; { register struct Picture *DrawPict = Pict->DrawPict; register LONG Left = DrawPict->CountX + DrawPict->LeftMarg; register LONG Top = DrawPict->CountY + DrawPict->TopMarg; ZoomBox( Pict ); if ( MouseX < Pict->NavLeft ) MouseX = Pict->NavLeft; if ( MouseY < Pict->NavTop ) MouseY = Pict->NavTop; if ( MouseX > Left ) MouseX = Left-1; if ( MouseY > Top ) MouseY = Top-1; Pict->NavBot = MouseY; Pict->NavRight = MouseX; Lens( Pict ); ZoomBox( Pict ); } static double ZoomAspectRatio; StartPropStrech( Pict ) register struct Picture *Pict; { ZoomAspectRatio = (double) (Pict->NavRight - Pict->NavLeft) / (double) (Pict->NavBot - Pict->NavTop); } PropStretchBox( Pict ) register struct Picture *Pict; { register LONG Left = Pict->LeftMarg; register LONG Top = Pict->DrawPict->CountY + Pict->TopMarg; register LONG CenterX = Pict->NavRight - Pict->NavLeft; register LONG CenterY = Pict->NavBot - Pict->NavTop; LONG NewLeft,NewRight,NewTop; ZoomBox( Pict ); CenterX = Pict->NavLeft + CenterX / 2; CenterY = Pict->NavTop + CenterY / 2; if ( MouseX > CenterX-4 ) MouseX = CenterX-4; if ( MouseY < CenterY+4 ) MouseY = CenterY+4; #if 0 if ( MouseX < Left ) MouseX = Left; /* don't let it flip */ if ( MouseY > Top ) MouseY = Top; #endif Top = MouseY - CenterY; Left = (LONG) ((float) Top * ZoomAspectRatio); NewLeft = CenterX - Left; NewRight = CenterX + Left; NewTop = CenterY - Top; if (NewLeft >= Pict->LeftMarg && NewRight < Pict->DrawPict->Window->Width - Pict->RightMarg && NewTop >= Pict->TopMarg ) { Pict->NavBot = MouseY; Pict->NavTop = NewTop; Pict->NavLeft = NewLeft; Pict->NavRight = NewRight; } Lens( Pict ); ZoomBox( Pict ); } #define MINXBOX (8 << XScale) #define MINYBOX (7 << YScale) FinishResize( Pict ) struct Picture *Pict; { register int t; if (Pict->NavBot < Pict->NavTop) { t = Pict->NavBot; Pict->NavBot = Pict->NavTop; Pict->NavTop = t; } if (Pict->NavRight < Pict->NavLeft) { t = Pict->NavRight; Pict->NavRight = Pict->NavLeft; Pict->NavLeft = t; } ZoomBox( Pict ); if (Pict->NavRight - Pict->NavLeft < MINXBOX ) Pict->NavRight = Pict->NavLeft + MINXBOX; if (Pict->NavBot - Pict->NavTop < MINYBOX ) Pict->NavBot = Pict->NavTop + MINYBOX; ZoomOnOff( Pict ); } DragZoomBox( Pict ) register struct Picture *Pict; { register struct Picture *DrawPict = Pict->DrawPict; register LONG Width, Height; ZoomBox( Pict ); Width = Pict->NavRight - Pict->NavLeft - HotSpotX; Height = Pict->NavBot - Pict->NavTop - HotSpotY; if ( MouseY < 1 ) MouseY = 1; if ( MouseX - HotSpotX < DrawPict->LeftMarg ) MouseX = DrawPict->LeftMarg + HotSpotX; if ( MouseY - HotSpotY < DrawPict->TopMarg ) MouseY = DrawPict->TopMarg + HotSpotY; if ( MouseX + Width >= DrawPict->CountX + DrawPict->LeftMarg ) MouseX = DrawPict->CountX + DrawPict->LeftMarg - Width; if ( MouseY + Height >= DrawPict->CountY + DrawPict->TopMarg ) MouseY = DrawPict->CountY + DrawPict->TopMarg - Height; Pict->NavLeft = MouseX - HotSpotX; Pict->NavTop = MouseY - HotSpotY; Pict->NavRight = MouseX + Width; Pict->NavBot = MouseY + Height; Lens( Pict ); ZoomBox( Pict ); } CloseZoomBox( Pict ) struct Picture *Pict; { if (Pict) { if (Pict->Flags & ZOOM_BOX_OPEN) { ZoomOnOff( Pict ); Remove( &Pict->zNode ); Pict->Flags &= ~ZOOM_BOX_OPEN; } Pict->DrawPict = NULL; } } ClearZoomBox(Pict) struct Picture *Pict; { CloseZoomBox( Pict ); ZoomedPict = NULL; } ZoomBox( Pict ) register struct Picture *Pict; { if ( Pict && Pict->DrawPict && Pict->DrawPict->Window) { ObtainSemaphore( &Pict->WindowSemi ); DrawBox( Pict->DrawPict->Window, Pict->NavLeft, Pict->NavTop, Pict->NavRight, Pict->NavBot ); ReleaseSemaphore( &Pict->WindowSemi ); } } ZoomExtras( Pict ) register struct Picture *Pict; { if ( Pict && Pict->DrawPict && Pict->DrawPict->Window) { ObtainSemaphore( &Pict->WindowSemi ); DrawExtras( Pict->DrawPict->Window, Pict->NavLeft, Pict->NavTop, Pict->NavRight, Pict->NavBot ); ReleaseSemaphore( &Pict->WindowSemi ); } } ZoomOnOff( Pict ) register struct Picture *Pict; { ZoomBox( Pict ); ZoomExtras( Pict ); } DrawBox( Window, PLeft, PTop, PRight, PBottom) struct Window *Window; SHORT PTop, PLeft, PBottom, PRight; { register struct RastPort *Rp; register LONG Top, Left, Right, Bottom; Rp = Window->RPort; Top = PTop; Left = PLeft; Right = PRight; Bottom = PBottom; SetDrMd(Rp, COMPLEMENT); /* * Draw the new box */ Move(Rp, Left, Top ); Draw(Rp, Right, Top ); Draw(Rp, Right, Bottom); Draw(Rp, Left, Bottom); Draw(Rp, Left, Top+1 ); SetDrMd(Rp, JAM1); } /* DrawBox */ DrawExtras( Window, Left, Top, Right, Bottom) struct Window *Window; SHORT Top, Left, Bottom, Right; { register struct RastPort *Rp = Window->RPort; register LONG ResizeTop = Bottom - ( BoxSizeY << YScale ); register LONG ResizeLeft = Right - ( BoxSizeX << XScale ); register LONG BotDrag = Top + ( DragSize << YScale ); SetDrMd(Rp, COMPLEMENT); /* * Draw Normal Resize gadget */ Move(Rp, (long) Right - 1, ResizeTop ); Draw(Rp, ResizeLeft, ResizeTop ); Draw(Rp, ResizeLeft, (long) Bottom - 1); /* * Draw Proportional Resize gadget */ ResizeLeft = Left + ( BoxSizeX << XScale ); Move(Rp, (long) Left + 1, ResizeTop ); Draw(Rp, ResizeLeft, ResizeTop ); Draw(Rp, ResizeLeft, (long) Bottom - 1); /* * Drag bar bar / close gadget separator */ Move(Rp, (long) Left + 1, BotDrag ); Draw(Rp, (long) Right - 1, BotDrag ); Move(Rp, (long) Left + (4 << XScale), (long) Top + 1); Draw(Rp, (long) Left + (4 << XScale), BotDrag - 1 ); SetDrMd(Rp, JAM1); } /* DrawExtras */ /* * ZoomIn */ ZoomIn( NavPict ) register struct Picture *NavPict; { register struct Picture *DrawPict = NavPict->DrawPict; double left, top; double right, bot; double AspectRatio(); double Gap; if (DrawPict) { left = (double) (NavPict->NavLeft - DrawPict->LeftMarg); top = (double) (NavPict->NavTop - DrawPict->TopMarg); right = (double) (NavPict->NavRight - DrawPict->LeftMarg); bot = (double) (NavPict->NavBot - DrawPict->TopMarg); switch( NavPict->ZoomType ) { case ZOOMIN: NavPict->RealHigh = DrawPict->RealLow + DrawPict->RealGap*right; NavPict->ImagHigh = DrawPict->ImagLow + DrawPict->ImagGap*bot; NavPict->RealLow = DrawPict->RealLow + DrawPict->RealGap*left; NavPict->ImagLow = DrawPict->ImagLow + DrawPict->ImagGap*top; NavPict->Real = DrawPict->Real; NavPict->Imag = DrawPict->Imag; break; case ZOOMOUT: Gap = (DrawPict->ImagHigh - DrawPict->ImagLow) / (bot - top); NavPict->ImagLow -= top * Gap; NavPict->ImagHigh = NavPict->ImagLow + (double) NavPict->CountY*Gap; NavPict->ImagGap = Gap; NavPict->RealGap = Gap *= AspectRatio(NavPict); NavPict->RealLow -= left * Gap; NavPict->RealHigh = NavPict->RealLow + (double) NavPict->CountX*Gap; } CloseZoomBox( NavPict ); } CalculateGaps( NavPict ); } /* ZoomIn */ /* * Calculate Gaps */ CalculateGaps( Pict ) register struct Picture *Pict; { double AspectRatio(); Pict->ImagGap = (Pict->ImagHigh - Pict->ImagLow) / (double) Pict->CountY; Pict->RealGap = Pict->ImagGap * AspectRatio( Pict ); } /* * Apsect Ratio - IEEE */ double AspectRatio( Pict ) register struct Picture *Pict; { double aspectratio; if (Pict->ViewModes & HIRES) if (Pict->ViewModes & INTERLACE) aspectratio = 0.88; else aspectratio = 0.44; else if (Pict->ViewModes & INTERLACE) aspectratio = 1.76; else aspectratio = 0.88; return( aspectratio ); } /* * Simulate Zoom box gadgets */ int CheckPictZoomBox( NavPict ) register struct Picture *NavPict; { register struct Picture *DrawPict = NavPict->DrawPict; register struct Window *Window = DrawPict->Window; register LONG BoxX; BoxX = BoxSizeX << XScale; /* is it in the window box? */ if (MouseX >= NavPict->NavLeft && MouseX <= NavPict->NavRight && MouseY >= NavPict->NavTop && MouseY <= NavPict->NavBot) { /* is it in the top part? */ if (MouseY <= NavPict->NavTop + (DragSize << YScale) ) { /* is it the drag bar? */ if (MouseX > NavPict->NavLeft + BoxX ) { HotSpotX = MouseX - NavPict->NavLeft; HotSpotY = MouseY - NavPict->NavTop; return(ZOOMDRAGHIT); } else { /* We got the close gadget */ return(ZOOMCLOSEHIT); } } else { /* is it the Resize Gadget? */ if (MouseY >= NavPict->NavBot - ((BoxSizeY + 1) << YScale) ) { if ( MouseX > NavPict->NavRight - BoxX ) { return(ZOOMRESIZEHIT); } else if ( MouseX <= NavPict->NavLeft + BoxX ) { return(PROPRESIZEHIT); } } } } return(NOTHINGHIT); } SetJuliaPt( ZoomedPict, Pict ) register struct Picture *ZoomedPict, *Pict; { register LONG x,y; if (ZoomedPict && Pict && ZoomedPict->pNode.ln_Type != Pict->pNode.ln_Type) { x = MouseX - Pict->LeftMarg; y = MouseY - Pict->TopMarg; ZoomedPict->Real = Pict->RealLow + x * Pict->RealGap; ZoomedPict->Imag = Pict->ImagLow + y * Pict->ImagGap; } }