📄 mapper.c
字号:
/********************************************************************* FILE: Mapper.c** DESCRIPTION: The Mapper user interface** VERSION: 1.0**********************************************************************/#include <PalmOS.h>#include <PalmCompatibility.h>#include "Map.h"#include "Utils.h"#include "UtilsRsc.h"#include "MapperRsc.h"#include "Mapper.h"// These are used by MainFormDraw. We don't get them from the gadget// because the draw routine needs to be fast.#define mapGadgetHeight ( 145 )#define mapGadgetWidth ( 145 )#define mapMinPenMoveForScroll ( 2 )#define mapHitRadius ( 6 )#define mapLabelHeight (12 )#define mapLabelWidth ( 120 )const RectangleType mapGadgetRect = { 0, 15, 145, 160 };// fast absolute value for integers.#define ABS( x ) ( ( x < 0 ? 0 - x : x ) )typedef enum _EMapZoomLevel{ mapZoomNone = 0, mapZoomLow = 1, mapZoomHigh = 2} EMapZoomLevel;typedef struct _TPanllInfo{ TMapInfoTypePtr mapP; PointType mapOrigin; EMapZoomLevel zoom; TMapLayerPtr layerP; TMapLabel layerLabelP; PointType layerPOICoord;} TPanllInfoType, *TPanllInfoTypePtr;// prototypesvoid MainFormZoom( PointType *mapPointP, TPanllInfoTypePtr panInfoP );static void MainFormStopPan( FormType *frmP // (in) Active Form);static void MainFormDoScroll( FormType *frmP, // Current form Coord dx, Coord dy // delta to scroll);static void MainFormDoMapTap( FormType *frmP, Coord x, Coord y // (in) point on which tap occurred);// utility function/*********************************************************************** * FUNCTION: RestrictToDisplay * * DESCRIPTION: This routine initializes the MainForm form. * * RETURNED: nothing ***********************************************************************/ static void RestrictToDisplay( TPanllInfoTypePtr panInfoP, // (in) current map scroll info Coord *xP, Coord *yP // (in) where we'd like to be // (out) where we should draw to keep the map on the screen){ PointType *fixPointP, *newPointP, point;// If the new point is outside the map bounds when drawn, clip appropriately. point.x = *xP; point.y = *yP; newPointP = MapCoordToScreenCoord( &point, &mapGadgetRect ); point.x = 0; point.y = 0; fixPointP = ScreenCoordToMapCoord( &point, &mapGadgetRect );// Clip x on the left if ( newPointP->x > mapGadgetRect.topLeft.x ) { *xP = fixPointP->x; }// Clip y on the top if ( newPointP->y > mapGadgetRect.topLeft.y ) { *yP = fixPointP->x; } point.x = panInfoP->mapP->mapBounds.extent.x + mapGadgetRect.topLeft.x; point.y = panInfoP->mapP->mapBounds.extent.y + mapGadgetRect.topLeft.y; fixPointP = ScreenCoordToMapCoord( &point, &mapGadgetRect );// Clip x on the right if ( newPointP->x + panInfoP->mapP->mapBounds.extent.x < mapGadgetRect.extent.x ) { *xP = ABS(fixPointP->x); }// Clip y on the bottom if ( newPointP->y + panInfoP->mapP->mapBounds.extent.y < mapGadgetRect.extent.y ) { *yP = ABS(fixPointP->y); }}/*********************************************************************** * FUNCTION: MainFormInit * * DESCRIPTION: This routine initializes the MainForm form. * * RETURNED: nothing ***********************************************************************/ static void MainFormInit( FormPtr frmP // Pointer to the MainForm form.){ TPanllInfoTypePtr panInfoP; Err anErr; UInt32 depth = 8; Boolean color = true; // Set up the map scrolling object. panInfoP = MemPtrNew( sizeof( TPanllInfoType ) ); panInfoP->mapP = MapFetchMap( mapBoulderCreek24, &anErr ); if ( anErr == noErr ) {// Begin by centering the map in the scrolling display. panInfoP->mapOrigin.x = panInfoP->mapP->mapBounds.extent.x / 2; panInfoP->mapOrigin.y = panInfoP->mapP->mapBounds.extent.y / 2; panInfoP->layerP = MapFetchLayer( mapBoulderCreek24, mapLayerPOI, &anErr ); panInfoP->zoom = mapZoomLow; MemSet( panInfoP->layerLabelP, sizeof( TMapLabel ), 0 ); panInfoP->layerPOICoord.x = panInfoP->layerPOICoord.y = 0; FrmSetGadgetData ( frmP, FrmGetObjectIndex ( frmP, MainMapGadget ), panInfoP ); } else { MemPtrFree( panInfoP ); FrmAlert( CantGetMapAlert ); }}/*********************************************************************** * FUNCTION: MainFormDrawMap * * DESCRIPTION: This routine draws the map * * RETURNED: nothing ***********************************************************************/inline static void MainFormDrawMap( TPanllInfoTypePtr panInfoP, PointType *screenPointP){ WinPaintBitmap( panInfoP->mapP->mapBitmapP, screenPointP->x, screenPointP->y );}/*********************************************************************** * FUNCTION: MainFormDrawMapLayer * * DESCRIPTION: This routine draws the map layer if necessary * * RETURNED: nothing ***********************************************************************/inline static void MainFormDrawMapLayer( TPanllInfoTypePtr panInfoP, PointType *screenPointP){ int i; TMapPOILayerItemPtr poiP; Handle layerBitmapH; BitmapType *layerBitmapP; int dx, dy;// If the layer's being displayed, draw stuff from the layer as well. if ( panInfoP->layerP ) { layerBitmapH = DmGetResource( bitmapRsc, 9900 ); if ( layerBitmapH ) { layerBitmapP = (BitmapType *)MemHandleLock( layerBitmapH ); // Get an offset -- we want to draw the icon centered over the POI. dx = layerBitmapP->width / 2; dy = layerBitmapP->height / 2; // For each POI, if it's on the current display, draw it. for ( i = 0; i < panInfoP->layerP->count; i++ ) { poiP = (TMapPOILayerItemPtr)&panInfoP->layerP->layerDataPtr[i]; screenPointP = MapCoordToTapCoord( &poiP->pos, &panInfoP->mapOrigin, &mapGadgetRect ); if ( RctPtInRectangle ( screenPointP->x, screenPointP->y, &mapGadgetRect) ) { WinPaintBitmap( layerBitmapP, screenPointP->x-dx, screenPointP->y-dy ); } } MemHandleUnlock( layerBitmapH ); DmReleaseResource( layerBitmapH ); } }}/*********************************************************************** * FUNCTION: MainFormDrawLabelLayer * * DESCRIPTION: This routine draws the map label layer if necessary * * RETURNED: nothing ***********************************************************************/static void MainFormDrawLabelLayer( TPanllInfoTypePtr panInfoP, PointType *screenPointP){ RectangleType rect; int width; int x, y;// If the layer's being displayed, draw stuff from the layer as well. if ( StrLen( panInfoP->layerLabelP ) > 0 ) { screenPointP = MapCoordToTapCoord( &panInfoP->layerPOICoord, &panInfoP->mapOrigin, &mapGadgetRect ); if ( RctPtInRectangle( screenPointP->x, screenPointP->y, &mapGadgetRect ) ) { width = min( FntCharsWidth( panInfoP->layerLabelP, StrLen( panInfoP->layerLabelP ) ), mapLabelWidth ); // Make sure the rectangle is on the screen. x = screenPointP->x - mapLabelWidth / 2 > mapGadgetRect.topLeft.x ? screenPointP->x - mapLabelWidth / 2 : mapGadgetRect.topLeft.x; x = ( x + width > mapGadgetRect.extent.x - 4 ) ? mapGadgetRect.extent.x - width - 4: x; y = screenPointP->y - 4 - mapLabelHeight > mapGadgetRect.topLeft.y ? screenPointP->y - 4 - mapLabelHeight : mapGadgetRect.topLeft.y; y = ( y + mapLabelHeight > mapGadgetRect.extent.y - 4 ) ? mapGadgetRect.extent.y - mapLabelHeight - 4 : y; RctSetRectangle ( &rect, x, y, width, mapLabelHeight ); screenPointP->x = rect.topLeft.x + 1; screenPointP->y = rect.topLeft.y + 1; WinEraseRectangle( &rect, 0 ); WinPaintRectangleFrame( popupFrame, &rect ); WinDrawTruncChars( panInfoP->layerLabelP, StrLen( panInfoP->layerLabelP ), screenPointP->x, screenPointP->y, mapLabelWidth - 2 ); } }}/*********************************************************************** * FUNCTION: MainFormDraw * * DESCRIPTION: This routine draws the non-form contents of the MainForm form. * * RETURNED: nothing ***********************************************************************/static void MainFormDraw( FormPtr frmP // Pointer to the MainForm form.){ if ( frmP != NULL ) { TPanllInfoTypePtr panInfoP; PointType mapPoint, *screenPointP; panInfoP = FrmGetGadgetData ( frmP, FrmGetObjectIndex ( frmP, MainMapGadget ) ); if ( !panInfoP ) return; mapPoint.x = panInfoP->mapOrigin.x; mapPoint.y = panInfoP->mapOrigin.y; screenPointP = MapCoordToScreenCoord( &mapPoint, &mapGadgetRect ); WinScreenLock( winLockCopy ); WinSetClip ( &mapGadgetRect ); WinPushDrawState( ); MainFormDrawMap ( panInfoP, screenPointP ); MainFormDrawMapLayer ( panInfoP, screenPointP ); MainFormDrawLabelLayer ( panInfoP, screenPointP ); WinPopDrawState ( ); WinResetClip (); WinScreenUnlock ( ); }}/*********************************************************************** * FUNCTION: MainFormDone * * DESCRIPTION: This routine cleans up after the Main form. * * RETURNED: nothing ***********************************************************************/static void MainFormDone( FormPtr frmP // Pointer to the MainForm form){ if ( frmP != NULL ) { TPanllInfoTypePtr panInfoP; panInfoP = FrmGetGadgetData ( frmP, FrmGetObjectIndex ( frmP, MainMapGadget ) ); // Deallocate the map window's bitmap and window if ( panInfoP && panInfoP->mapP ) { MapReleaseMap( panInfoP->mapP->mapID, panInfoP->mapP ); MapReleaseLayer( panInfoP->mapP->mapID, panInfoP->layerP );// Free the gadget's memory MemPtrFree( panInfoP ); } // Then do this as the very last thing FrmEraseForm ( frmP ); FrmDeleteForm ( frmP ); }}/*********************************************************************** * FUNCTION: MainFormStartPan * * DESCRIPTION: Call before scrolling the map. * * RETURNED: nothing ***********************************************************************/static void MainFormStartPan( FormType *frmP // (in) Active Form){ #pragma unused( frmP ) Boolean penDown; Coord x, y; Coord firstX, firstY; Coord currX, currY; Coord dx, dy; // initialize EvtGetPen (&currX, &currY, &penDown); firstX = currX; firstY = currY; // loop while the pen is down and scroll while( penDown == true ) { EvtGetPen (&x, &y, &penDown); dx = x - currX; dy = y - currY; MainFormDoScroll( frmP, dx, dy ); currX = x; currY = y; } // handle pen up if ( ABS( firstX - currX ) < mapMinPenMoveForScroll && ABS( firstX - currY ) < mapMinPenMoveForScroll ) { MainFormDoMapTap( frmP, firstX, firstY ); } MainFormStopPan( frmP ); }/*********************************************************************** * FUNCTION: MainFormStopPan * * DESCRIPTION: Call after scrolling the map. * * RETURNED: nothing ***********************************************************************/static void MainFormStopPan( FormType *frmP // (in) Active Form){ #pragma unused( frmP )}/*********************************************************************** * FUNCTION: MainFormDoScroll * * DESCRIPTION: This routine scrolls the map the specified amount * * RETURNED: nothing ***********************************************************************/static void MainFormDoScroll( FormType *frmP, // Current form Coord dx, Coord dy // delta to scroll){ TPanllInfoTypePtr panInfoP; Coord newX, newY; panInfoP = FrmGetGadgetData ( frmP, FrmGetObjectIndex ( frmP, MainMapGadget ) ); if ( !panInfoP ) return; // Secret sauce: scroll the map 2x as fast as pen moves.// Makes scrolling large maps easier, and gives a "psychic feel" to the// gadget. dx *= 2; dy *= 2; newX = panInfoP->mapOrigin.x - dx; newY = panInfoP->mapOrigin.y - dy; RestrictToDisplay( panInfoP, &newX, &newY );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -