summaryrefslogtreecommitdiff
path: root/app/bin/cselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/bin/cselect.c')
-rw-r--r--app/bin/cselect.c261
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 );