diff options
Diffstat (limited to 'app/bin/cselect.c')
-rw-r--r-- | app/bin/cselect.c | 261 |
1 files changed, 230 insertions, 31 deletions
diff --git a/app/bin/cselect.c b/app/bin/cselect.c index 1bafd45..861f03f 100644 --- a/app/bin/cselect.c +++ b/app/bin/cselect.c @@ -1,8 +1,5 @@ /** \file cselect.c * Handle selecting / unselecting track and basic operations on the selection - * - * $Header: /home/dmarkle/xtrkcad-fork-cvs/xtrkcad/app/bin/cselect.c,v 1.11 2008-09-05 08:08:15 m_fischer Exp $ - * */ /* XTrkCad - Model Railroad CAD @@ -23,19 +20,30 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "track.h" -/*#include "trackx.h"*/ +#include <math.h> +#include <string.h> + #include "ccurve.h" +#include "tcornu.h" +#include "tbezier.h" #define PRIVATE_EXTRADATA #include "compound.h" +#include "cselect.h" +#include "cundo.h" +#include "custom.h" +#include "fileio.h" +#include "i18n.h" +#include "layout.h" +#include "messages.h" +#include "param.h" +#include "track.h" +#include "utility.h" #include "bitmaps/bmendpt.xbm" #include "bitmaps/bma0.xbm" #include "bitmaps/bma45.xbm" #include "bitmaps/bma90.xbm" #include "bitmaps/bma135.xbm" -#include "i18n.h" - #define SETMOVEMODE "MOVEMODE" @@ -55,8 +63,10 @@ static wDrawBitMap_p angle_bm[4]; long quickMove = 0; BOOL_T importMove = 0; int incrementalDrawLimit = 20; + static int microCount = 0; static dynArr_t tlist_da; + #define Tlist(N) DYNARR_N( track_p, tlist_da, N ) #define TlistAppend( T ) \ { DYNARR_APPEND( track_p, tlist_da, 10 );\ @@ -143,6 +153,7 @@ EXPORT void SetAllTrackSelect( BOOL_T select ) SelectedTrackCountChange(); if (doRedraw) { MainRedraw(); + MapRedraw(); } else { wDrawDelayUpdate( mainD.d, FALSE ); } @@ -174,6 +185,7 @@ EXPORT void InvertTrackSelect( void *ptr ) SelectedTrackCountChange(); MainRedraw(); + MapRedraw(); } /* Select orphaned (ie single) track pieces. @@ -207,6 +219,7 @@ EXPORT void OrphanedTrackSelect( void *ptr ) } SelectedTrackCountChange(); MainRedraw(); + MapRedraw(); } @@ -389,7 +402,7 @@ EXPORT void SelectTunnel( void ) } -EXPORT void SelectRecount( void ) +void SelectRecount( void ) { track_p trk; selectedTrackCount = 0; @@ -518,6 +531,7 @@ EXPORT void DoRefreshCompound( void ) RefreshCompound( NULL, FALSE ); UndoEnd(); MainRedraw(); + MapRedraw(); } else { ErrorMessage( MSG_NO_SELECTED_TRK ); } @@ -766,9 +780,9 @@ EXPORT void DoRescale( void ) if ( rescalePG.win == NULL ) { ParamCreateDialog( &rescalePG, MakeWindowTitle(_("Rescale")), _("Ok"), RescaleDlgOk, wHide, TRUE, NULL, F_BLOCK, RescaleDlgUpdate ); LoadScaleList( (wList_p)rescalePLs[I_RESCALE_TO_SCALE].control ); - LoadGaugeList( (wList_p)rescalePLs[I_RESCALE_TO_GAUGE].control, curScaleDescInx ); /* set correct gauge list here */ - rescaleFromScaleInx = curScaleInx; - rescaleToScaleInx = curScaleInx; + LoadGaugeList( (wList_p)rescalePLs[I_RESCALE_TO_GAUGE].control, GetLayoutCurScaleDesc() ); /* set correct gauge list here */ + rescaleFromScaleInx = GetLayoutCurScale(); + rescaleToScaleInx = rescaleFromScaleInx; rescalePercent = 100.0; } @@ -1032,6 +1046,10 @@ static void MoveTracks( track_p trk, trk1; EPINX_T ep, ep1; int inx; + trackParams_t trackParms; + ANGLE_T endAngle; + DIST_T endRadius; + coOrd endCenter; wSetCursor( wCursorWait ); /*UndoStart( "Move/Rotate Tracks", "move/rotate" );*/ @@ -1050,12 +1068,57 @@ static void MoveTracks( RotateTrack( trk, orig, angle ); for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { if ((trk1 = GetTrkEndTrk(trk,ep)) != NULL && - !GetTrkSelected(trk1)) { + !GetTrkSelected(trk1)) { ep1 = GetEndPtConnectedToMe( trk1, trk ); DisconnectTracks( trk, ep, trk1, ep1 ); + if (QueryTrack(trk1,Q_IS_CORNU)) { //Cornu at end stays connected + GetTrackParams(PARAMS_CORNU,trk,GetTrkEndPos(trk,ep),&trackParms); + if (trackParms.type == curveTypeStraight) { + endRadius = 0; + endCenter = zero; + } else { + endRadius = trackParms.arcR; + endCenter = trackParms.arcP; + } + DrawTrack(trk1,&mainD,wDrawColorWhite); + DrawTrack(trk1,&mapD,wDrawColorWhite); + endAngle = NormalizeAngle(GetTrkEndAngle(trk,ep)+180); + if (SetCornuEndPt(trk1,ep1,GetTrkEndPos(trk,ep),endCenter,endAngle,endRadius)) { + ConnectTracks(trk,ep,trk1,ep1); + DrawTrack(trk1,&mainD,wDrawColorBlack); + DrawTrack(trk1,&mapD,wDrawColorBlack); + } else { + DeleteTrack(trk1,TRUE); + ErrorMessage(_("Cornu too tight - it was deleted")); + } + } else { + if (QueryTrack(trk,Q_IS_CORNU)) { //I am a Cornu myself! + GetTrackParams(PARAMS_CORNU,trk1,GetTrkEndPos(trk1,ep1),&trackParms); + if (trackParms.type == curveTypeStraight) { + endRadius = 0; + endCenter = zero; + } else { + endRadius = trackParms.arcR; + endCenter = trackParms.arcP; + } + DrawTrack(trk,&mainD,wDrawColorWhite); + DrawTrack(trk1,&mapD,wDrawColorWhite); + endAngle = NormalizeAngle(GetTrkEndAngle(trk1,ep1)+180); + if (SetCornuEndPt(trk,ep,GetTrkEndPos(trk1,ep1),endCenter,endAngle,endRadius)) { + ConnectTracks(trk,ep,trk1,ep1); + DrawTrack(trk,&mainD,wDrawColorBlack); + DrawTrack(trk,&mapD,wDrawColorBlack); + } else { + ErrorMessage(_("Cornu selected too tight after move - it was left alone")); + DrawTrack(trk,&mainD,wDrawColorBlack); + DrawTrack(trk,&mapD,wDrawColorBlack); + } + } + } DrawEndPt( &mainD, trk1, ep1, wDrawColorBlack ); } } + InfoCount( inx ); #ifdef LATER if (tlist_da.cnt <= incrementalDrawLimit) @@ -1103,6 +1166,16 @@ void MoveToJoin( DrawNewTrack( trk0 ); DrawNewTrack( trk1 ); } + +void FreeTempStrings() { + for (int i = 0; i<tempSegs_da.cnt; i++) { + if (tempSegs(i).type == SEG_TEXT) { + if (tempSegs(i).u.t.string) + MyFree(tempSegs(i).u.t.string); + tempSegs(i).u.t.string = NULL; + } + } +} static STATUS_T CmdMove( wAction_t action, @@ -1112,7 +1185,7 @@ static STATUS_T CmdMove( static coOrd orig; static int state; - switch( action ) { + switch( action&0xFF) { case C_START: if (selectedTrackCount == 0) { @@ -1122,7 +1195,7 @@ static STATUS_T CmdMove( if (SelectedTracksAreFrozen()) { return C_TERMINATE; } - InfoMessage( _("Drag to move selected tracks") ); + InfoMessage( _("Drag to move selected tracks - Shift+Ctrl+Arrow micro-steps the move") ); state = 0; break; case C_DOWN: @@ -1134,19 +1207,20 @@ static STATUS_T CmdMove( orig = pos; GetMovedTracks(quickMove != MOVE_QUICK); SetMoveD( TRUE, base, 0.0 ); - DrawMovedTracks(); + //DrawMovedTracks(); drawCount = 0; state = 1; MainRedraw(); + MapRedraw(); return C_CONTINUE; case C_MOVE: drawEnable = enableMoveDraw; - DrawMovedTracks(); + //DrawMovedTracks(); base.x = pos.x - orig.x; base.y = pos.y - orig.y; SnapPos( &base ); SetMoveD( TRUE, base, 0.0 ); - DrawMovedTracks(); + //DrawMovedTracks(); #ifdef DRAWCOUNT InfoMessage( " [%s %s] #%ld", FormatDistance(base.x), FormatDistance(base.y), drawCount ); #else @@ -1154,10 +1228,12 @@ static STATUS_T CmdMove( #endif drawEnable = TRUE; MainRedraw(); + MapRedraw(); return C_CONTINUE; case C_UP: state = 0; - DrawMovedTracks(); + //DrawMovedTracks(); + FreeTempStrings(); MoveTracks( quickMove==MOVE_QUICK, TRUE, FALSE, base, zero, 0.0 ); return C_TERMINATE; @@ -1173,6 +1249,47 @@ static STATUS_T CmdMove( DrawMovedTracks(); break; + case wActionExtKey: + if (state) return C_CONTINUE; + if (SelectedTracksAreFrozen()) return C_TERMINATE; + if ((MyGetKeyState() & + (WKEY_SHIFT | WKEY_CTRL)) == (WKEY_SHIFT | WKEY_CTRL)) { + base = zero; + DIST_T w = tempD.scale/tempD.dpi; + switch((wAccelKey_e) action>>8) { + case wAccelKey_Up: + base.y = w; + break; + case wAccelKey_Down: + base.y = -w; + break; + case wAccelKey_Left: + base.x = -w; + break; + case wAccelKey_Right: + base.x = w; + break; + default: + return C_CONTINUE; + break; + } + + drawEnable = enableMoveDraw; + GetMovedTracks(quickMove!=MOVE_QUICK); + UndoStart( _("Move Tracks"), "move" ); + SetMoveD( TRUE, base, 0.0 ); + DrawSelectedTracksD( &mainD, wDrawColorWhite ); + MoveTracks( quickMove==MOVE_QUICK, TRUE, FALSE, base, zero, 0.0 ); + ++microCount; + if (microCount>5) { + microCount = 0; + MainRedraw(); + MapRedraw(); + } + return C_CONTINUE; + } + break; + default: break; } @@ -1214,7 +1331,7 @@ static STATUS_T CmdRotate( if (SelectedTracksAreFrozen()) { return C_TERMINATE; } - InfoMessage( _("Drag to rotate selected tracks") ); + InfoMessage( _("Drag to rotate selected tracks, Shift+RightClick for QuickRotate Menu") ); wMenuPushEnable( rotateAlignMI, TRUE ); rotateAlignState = 0; break; @@ -1226,9 +1343,22 @@ static STATUS_T CmdRotate( UndoStart( _("Rotate Tracks"), "rotate" ); if ( rotateAlignState == 0 ) { drawnAngle = FALSE; - angle = 0; + angle = 0.0; base = orig = pos; + trk = OnTrack(&pos, FALSE, FALSE); //Note pollutes pos if turntable + if ((trk) && + QueryTrack(trk,Q_CAN_ADD_ENDPOINTS)) { //Turntable snap to center if within 1/4 radius + trackParams_t trackParams; + if (GetTrackParams(PARAMS_CORNU, trk, pos, &trackParams)) { + DIST_T dist = FindDistance(base, trackParams.ttcenter); + if (dist < trackParams.ttradius/4) { + base = orig = trackParams.ttcenter; + InfoMessage( _("Center of Rotation snapped to Turntable center") ); + } + } + } GetMovedTracks(FALSE); + SetMoveD( FALSE, base, angle ); /*DrawLine( &mainD, base, orig, 0, wDrawColorBlack ); DrawMovedTracks(FALSE, orig, angle);*/ } else { @@ -1256,20 +1386,21 @@ static STATUS_T CmdRotate( angle = 0; } else { angle = NormalizeAngle(angle1-baseAngle); - if ( angle > 90 && angle < 270 ) - angle = NormalizeAngle( angle + 180.0 ); - if ( NormalizeAngle( FindAngle( pos, pos1 ) - angle1 ) < 180.0 ) - angle = NormalizeAngle( angle + 180.0 ); + //if ( angle > 90 && angle < 270 ) + // angle = NormalizeAngle( angle + 180.0 ); + //if ( NormalizeAngle( FindAngle( base, pos1 ) - angle1 ) < 180.0 ) + // angle = NormalizeAngle( angle + 180.0 ); /*printf( "angle 1 = %0.3f\n", angle );*/ if ( angle1 > 180.0 ) angle1 -= 180.0; InfoMessage( _("Angle %0.3f"), angle1 ); } GetMovedTracks(TRUE); SetMoveD( FALSE, orig, angle ); - DrawMovedTracks(); + //DrawMovedTracks(); } } MainRedraw(); + MapRedraw(); return C_CONTINUE; case C_MOVE: if ( rotateAlignState == 1 ) @@ -1285,7 +1416,7 @@ static STATUS_T CmdRotate( ErrorMessage( MSG_2ND_TRACK_MUST_BE_UNSELECTED ); return C_CONTINUE; } - DrawMovedTracks(); + //DrawMovedTracks(); angle1 = NormalizeAngle( GetAngleAtPoint( trk, pos, NULL, NULL ) ); angle = NormalizeAngle(angle1-baseAngle); if ( angle > 90 && angle < 270 ) @@ -1296,8 +1427,9 @@ static STATUS_T CmdRotate( InfoMessage( _("Angle %0.3f"), angle1 ); SetMoveD( FALSE, orig, angle ); /*printf( "angle 2 = %0.3f\n", angle );*/ - DrawMovedTracks(); + //DrawMovedTracks(); MainRedraw(); + MapRedraw(); return C_CONTINUE; } if ( FindDistance( orig, pos ) > (6.0/75.0)*mainD.scale ) { @@ -1321,7 +1453,7 @@ static STATUS_T CmdRotate( } DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); SetMoveD( FALSE, orig, angle ); - DrawMovedTracks(); + //DrawMovedTracks(); #ifdef DRAWCOUNT InfoMessage( _(" Angle %0.3f #%ld"), angle, drawCount ); #else @@ -1331,6 +1463,7 @@ static STATUS_T CmdRotate( drawEnable = TRUE; } MainRedraw(); + MapRedraw(); return C_CONTINUE; case C_UP: state = 0; @@ -1341,19 +1474,33 @@ static STATUS_T CmdRotate( } return C_CONTINUE; } + FreeTempStrings(); if ( rotateAlignState == 2 ) { - DrawMovedTracks(); + //DrawMovedTracks(); MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, orig, angle ); rotateAlignState = 0; } else if (drawnAngle) { DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); - DrawMovedTracks(); + //DrawMovedTracks(); MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, orig, angle ); } MainRedraw(); + MapRedraw(); return C_TERMINATE; case C_CMDMENU: + base = pos; + trk = OnTrack(&pos, FALSE, FALSE); //Note pollutes pos if turntable + if ((trk) && + QueryTrack(trk,Q_CAN_ADD_ENDPOINTS)) { //Turntable snap to center if within 1/4 radius + trackParams_t trackParams; + if (GetTrackParams(PARAMS_CORNU, trk, pos, &trackParams)) { + DIST_T dist = FindDistance(base, trackParams.ttcenter); + if (dist < trackParams.ttradius/4) { + cmdMenuPos = trackParams.ttcenter; + } + } + } wMenuPopupShow( selectPopup2M ); return C_CONTINUE; @@ -1371,6 +1518,20 @@ static STATUS_T CmdRotate( return C_CONTINUE; } +static void QuickMove( void* pos) { + coOrd move_pos = *(coOrd*)pos; + if ( SelectedTracksAreFrozen() ) + return; + wDrawDelayUpdate( mainD.d, TRUE ); + GetMovedTracks(FALSE); + DrawSelectedTracksD( &mainD, wDrawColorWhite ); + UndoStart( _("Move Tracks"), "Move Tracks" ); + MoveTracks( quickMove==MOVE_QUICK, TRUE, FALSE, move_pos, zero, 0.0 ); + wDrawDelayUpdate( mainD.d, FALSE ); + MainRedraw(); + MapRedraw(); +} + static void QuickRotate( void* pangle ) { ANGLE_T angle = (ANGLE_T)(long)pangle; @@ -1382,6 +1543,8 @@ static void QuickRotate( void* pangle ) UndoStart( _("Rotate Tracks"), "Rotate Tracks" ); MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, cmdMenuPos, angle ); wDrawDelayUpdate( mainD.d, FALSE ); + MainRedraw(); + MapRedraw(); } @@ -1460,11 +1623,26 @@ STATUS_T CmdMoveDescription( ep = -1; mode = 2; } + d = CornuDescriptionDistance( pos, trk1 ); + if ( d < dd ) { + dd = d; + trk = trk1; + ep = -1; + mode = 3; + } + d = BezierDescriptionDistance( pos, trk1 ); + if ( d < dd ) { + dd = d; + trk = trk1; + ep = -1; + mode = 4; + } } if (trk != NULL) { UndoStart( _("Move Label"), "Modedesc( T%d )", GetTrkIndex(trk) ); UndoModify( trk ); } + /* no break */ case C_MOVE: case C_UP: case C_REDRAW: @@ -1478,9 +1656,13 @@ STATUS_T CmdMoveDescription( return CompoundDescriptionMove( trk, action, pos ); case 2: return CurveDescriptionMove( trk, action, pos ); + case 3: + return CornuDescriptionMove( trk, action, pos ); + case 4: + return BezierDescriptionMove( trk, action, pos ); } } - + break; case C_CMDMENU: moveDescTrk = OnTrack( &pos, TRUE, FALSE ); if ( moveDescTrk == NULL ) break; @@ -1579,6 +1761,7 @@ static STATUS_T CmdFlip( pos0 = pos1 = pos; DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); MainRedraw(); + MapRedraw(); return C_CONTINUE; case C_MOVE: DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); @@ -1586,6 +1769,7 @@ static STATUS_T CmdFlip( DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); InfoMessage( _("Angle %0.2f"), FindAngle( pos0, pos1 ) ); MainRedraw(); + MapRedraw(); return C_CONTINUE; case C_UP: DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); @@ -1593,6 +1777,7 @@ static STATUS_T CmdFlip( FlipTracks( pos0, FindAngle( pos0, pos1 ) ); state = 0; MainRedraw(); + MapRedraw(); return C_TERMINATE; #ifdef LATER @@ -1821,6 +2006,18 @@ static STATUS_T CmdSelect( if (selectedTrackCount <= 0) { wMenuPopupShow( selectPopup1M ); } else { + coOrd base = pos; + track_p trk = OnTrack(&pos, FALSE, FALSE); //Note pollutes pos if turntable + if ((trk) && + QueryTrack(trk,Q_CAN_ADD_ENDPOINTS)) { //Turntable snap to center if within 1/4 radius + trackParams_t trackParams; + if (GetTrackParams(PARAMS_CORNU, trk, pos, &trackParams)) { + DIST_T dist = FindDistance(base, trackParams.ttcenter); + if (dist < trackParams.ttradius/4) { + cmdMenuPos = trackParams.ttcenter; + } + } + } wMenuPopupShow( selectPopup2M ); } return C_CONTINUE; @@ -1871,6 +2068,8 @@ EXPORT void InitCmdSelect( wMenu_p menu ) quickMove2M[1] = wMenuToggleCreate( selectPopup2M, "", _("Simple"), 0, quickMove==1, ChangeQuickMove, (void *) 1 ); quickMove2M[2] = wMenuToggleCreate( selectPopup2M, "", _("End Points"), 0, quickMove==2, ChangeQuickMove, (void *) 2 ); wMenuSeparatorCreate( selectPopup2M ); + AddMoveMenu( selectPopup2M, QuickMove); + wMenuSeparatorCreate( selectPopup2M ); AddRotateMenu( selectPopup2M, QuickRotate ); rotateAlignMI = wMenuPushCreate( selectPopup2M, "", _("Align"), 0, (wMenuCallBack_p)RotateAlign, NULL ); ParamRegister( &rescalePG ); |