📄 mapper.c
字号:
/********************************************************************* FILE: Mapper.c** DESCRIPTION: The Main Interface for Mapper** 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 _TPanInfo{ TMapInfoTypePtr mapP; PointType mapOrigin; EMapZoomLevel zoom; TMapLayerPtr layerP; TMapLabel layerLabelP; PointType layerPOICoord;} TPanInfoType, *TPanInfoTypePtr;// prototypesvoid MainFormZoom( PointType *mapPointP, TPanInfoTypePtr panInfoP );// utility function/*********************************************************************** * FUNCTION: RestrictToDisplay * * DESCRIPTION: This routine initializes the MainForm form. * * RETURNED: nothing ***********************************************************************/ static void RestrictToDisplay( TPanInfoTypePtr 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.){ TPanInfoTypePtr panInfoP; Err anErr; UInt32 depth = 8; Boolean color = true; // Set up the map panning object. panInfoP = MemPtrNew( sizeof( TPanInfoType ) ); panInfoP->mapP = MapFetchMap( mapBoulderCreek24, &anErr ); if ( anErr == noErr ) {// Begin by centering the map in the panning 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( TPanInfoTypePtr 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( TPanInfoTypePtr 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( TPanInfoTypePtr 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 ) { TPanInfoTypePtr 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 ); WinPushDrawState( ); WinSetClip ( &mapGadgetRect ); MainFormDrawMap ( panInfoP, screenPointP ); MainFormDrawMapLayer ( panInfoP, screenPointP ); MainFormDrawLabelLayer ( panInfoP, screenPointP ); WinResetClip (); WinPopDrawState ( ); }}/*********************************************************************** * 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 ) { TPanInfoTypePtr 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 panning the map. * * RETURNED: nothing ***********************************************************************/static void MainFormStartPan( FormType *frmP // (in) Active Form){ #pragma unused( frmP )}/*********************************************************************** * FUNCTION: MainFormStopPan * * DESCRIPTION: Call after panning the map. * * RETURNED: nothing ***********************************************************************/static void MainFormStopPan( FormType *frmP // (in) Active Form){ #pragma unused( frmP )}/*********************************************************************** * FUNCTION: MainFormDoPan * * DESCRIPTION: This routine scrolls the map the specified amount * * RETURNED: nothing ***********************************************************************/static void MainFormDoPan( FormType *frmP, // Current form Coord dx, Coord dy // delta to scroll){ TPanInfoTypePtr 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 panning 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 ); // Save the new origin and redraw the map. panInfoP->mapOrigin.x = newX; panInfoP->mapOrigin.y = newY; MainFormDraw( frmP ); }/*********************************************************************** * FUNCTION: MainFormDoMenuCommand * * DESCRIPTION: This routine handles menu commands. * * RETURNED: nothing ***********************************************************************/ static Boolean MainFormDoMenuCommand( UInt16 command // The ID of menu command to do){ Boolean handled = false; FormPtr frmP; switch ( command ) { case MainOptionsAboutMapper: MenuEraseStatus ( 0 ); frmP = FrmInitForm ( AboutForm ); FrmDoDialog ( frmP ); FrmDeleteForm ( frmP ); handled = true; break; } return handled;}/*********************************************************************** * FUNCTION: MainFormPOI * * DESCRIPTION: This routine searches under the given coordinate for a POI. * * RETURNED: the index of the POI, or -1 if no POI was hit. ***********************************************************************/static int MainFormPOI( PointType *mapPointP, TPanInfoTypePtr panInfoP ){ int poiIdx = -1; RectangleType hitRect; int i; TMapPOILayerItemPtr poiP; // Only look for a POI if the POI layer is on. if ( panInfoP->layerP ) {// Initialize the target rectangle. RctSetRectangle ( &hitRect, mapPointP->x-mapHitRadius,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -