diff options
author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-08-24 21:26:53 +0200 |
---|---|---|
committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-08-24 21:26:53 +0200 |
commit | df247efec654e512242e4f4f1b0212034f9e01fe (patch) | |
tree | 25c02e16957f3aa613af30c140fd8e8a3d52fda6 /app/bin/cselect.c | |
parent | d0b6a8a4ec298024f14f704f9e40a6f9d324ccf3 (diff) | |
parent | a5ade52caa489cf0a713e0f02b764000d203140e (diff) |
Merge branch 'release/debian/1%5.2.0Beta2.1-1' into masterdebian/1%5.2.0Beta2.1-1
Diffstat (limited to 'app/bin/cselect.c')
-rw-r--r-- | app/bin/cselect.c | 2238 |
1 files changed, 1768 insertions, 470 deletions
diff --git a/app/bin/cselect.c b/app/bin/cselect.c index 8ff68c0..4e4e8eb 100644 --- a/app/bin/cselect.c +++ b/app/bin/cselect.c @@ -23,9 +23,11 @@ #include <math.h> #include <string.h> +#include "draw.h" #include "ccurve.h" #include "tcornu.h" #include "tbezier.h" +#include "track.h" #define PRIVATE_EXTRADATA #include "compound.h" #include "cselect.h" @@ -38,6 +40,10 @@ #include "param.h" #include "track.h" #include "utility.h" +#include "draw.h" +#include "misc.h" +#include "trackx.h" + #include "bitmaps/bmendpt.xbm" #include "bitmaps/bma0.xbm" @@ -59,10 +65,12 @@ struct extraData { char junk[2000]; }; static wDrawBitMap_p endpt_bm; static wDrawBitMap_p angle_bm[4]; +track_p IsInsideABox(coOrd pos); - long quickMove = 0; - BOOL_T importMove = 0; - int incrementalDrawLimit = 20; +static track_p moveDescTrk; +static coOrd moveDescPos; + +int incrementalDrawLimit = 20; static int microCount = 0; static dynArr_t tlist_da; @@ -71,12 +79,169 @@ static dynArr_t tlist_da; #define TlistAppend( T ) \ { DYNARR_APPEND( track_p, tlist_da, 10 );\ Tlist(tlist_da.cnt-1) = T; } -static track_p *tlist2 = NULL; + +BOOL_T TListSearch(track_p T) { + for (int i=0;i<tlist_da.cnt-1;i++) { \ + if (Tlist(i) == T) return TRUE; + } + return FALSE; +} static wMenu_p selectPopup1M; +static wMenu_p selectPopup1CM; static wMenu_p selectPopup2M; +static wMenu_p selectPopup2CM; +static wMenu_p selectPopup2RM; +static wMenu_p selectPopup2TM; +static wMenu_p selectPopup2TYM; +static wMenuPush_p menuPushModify; +static wMenuPush_p rotateAlignMI; +static wMenuPush_p descriptionMI; +static wMenuPush_p hideMI; +static wMenuPush_p bridgeMI; +static wMenuPush_p tiesMI; + + +static BOOL_T doingAlign = FALSE; +static enum { AREA, MOVE } mode; +static void SelectOneTrack( + track_p trk, + wBool_t selected ); static void DrawSelectedTracksD( drawCmd_p d, wDrawColor color ); + +static dynArr_t anchors_da; +#define anchors(N) DYNARR_N(trkSeg_t,anchors_da,N) + +void CreateArrowAnchor(coOrd pos,ANGLE_T a,DIST_T len) { + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = SEG_STRLIN; + anchors(i).width = 0; + anchors(i).u.l.pos[0] = pos; + Translate(&anchors(i).u.l.pos[1],pos,NormalizeAngle(a+135),len); + anchors(i).color = wDrawColorBlue; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + i = anchors_da.cnt-1; + anchors(i).type = SEG_STRLIN; + anchors(i).width = 0; + anchors(i).u.l.pos[0] = pos; + Translate(&anchors(i).u.l.pos[1],pos,NormalizeAngle(a-135),len); + anchors(i).color = wDrawColorBlue; +} + +void static CreateRotateAnchor(coOrd pos) { + DIST_T d = tempD.scale*0.15; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = SEG_CRVLIN; + anchors(i).width = d/8; + anchors(i).u.c.center = pos; + anchors(i).u.c.a0 = 180.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).u.c.radius = d*2; + anchors(i).color = wDrawColorAqua; + coOrd head; //Arrows + for (int j=0;j<3;j++) { + Translate(&head,pos,j*120,d*2); + CreateArrowAnchor(head,NormalizeAngle((j*120)+90),d); + } +} + +void static CreateModifyAnchor(coOrd pos) { + DIST_T d = tempD.scale*0.15; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = SEG_FILCRCL; + anchors(i).width = 0; + anchors(i).u.c.center = pos; + anchors(i).u.c.a0 = 180.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).u.c.radius = d/2; + anchors(i).color = wDrawColorPowderedBlue; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + i = anchors_da.cnt-1; + anchors(i).type = SEG_CRVLIN; + anchors(i).width = 0; + anchors(i).u.c.center = pos; + anchors(i).u.c.a0 = 180.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).u.c.radius = d; + anchors(i).color = wDrawColorPowderedBlue; + +} + +void CreateDescribeAnchor(coOrd pos) { + DIST_T d = tempD.scale*0.15; + for (int j=0;j<2;j++) { + pos.x += j*d*3/4; + pos.y += j*d/2; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = SEG_CRVLIN; + anchors(i).width = d/4; + anchors(i).u.c.center = pos; + anchors(i).u.c.a0 = 270.0; + anchors(i).u.c.a1 = 270.0; + anchors(i).u.c.radius = d*3/4; + anchors(i).color = wDrawColorPowderedBlue; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + i = anchors_da.cnt-1; + anchors(i).type = SEG_STRLIN; + anchors(i).width = d/4; + Translate(&anchors(i).u.l.pos[0],pos,180.0,d*3/4); + Translate(&anchors(i).u.l.pos[1],pos,180.0,d*1.5); + anchors(i).color = wDrawColorPowderedBlue; + } +} + +void CreateActivateAnchor(coOrd pos) { + DIST_T d = tempD.scale*0.15; + coOrd c = pos; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = SEG_CRVLIN; + anchors(i).width = 0; + c.x -= d*3/4; + anchors(i).u.c.center = c; + anchors(i).u.c.a0 = 0.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).u.c.radius = d; + anchors(i).color = wDrawColorPowderedBlue; + DYNARR_APPEND(trkSeg_t,anchors_da,1); + i = anchors_da.cnt-1; + c.x += d*1.5; + anchors(i).type = SEG_CRVLIN; + anchors(i).width = 0; + anchors(i).u.c.center = pos; + anchors(i).u.c.a0 = 0.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).u.c.radius = d; + anchors(i).color = wDrawColorPowderedBlue; +} + +void static CreateMoveAnchor(coOrd pos) { + DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); + DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),pos,0,TRUE,wDrawColorBlue); + DYNARR_SET(trkSeg_t,anchors_da,anchors_da.cnt+5); + DrawArrowHeads(&DYNARR_N(trkSeg_t,anchors_da,anchors_da.cnt-5),pos,90,TRUE,wDrawColorBlue); +} + +void CreateEndAnchor(coOrd p, wBool_t lock) { + DIST_T d = tempD.scale*0.15; + + DYNARR_APPEND(trkSeg_t,anchors_da,1); + int i = anchors_da.cnt-1; + anchors(i).type = lock?SEG_FILCRCL:SEG_CRVLIN; + anchors(i).color = wDrawColorBlue; + anchors(i).u.c.center = p; + anchors(i).u.c.radius = d/2; + anchors(i).u.c.a0 = 0.0; + anchors(i).u.c.a1 = 360.0; + anchors(i).width = 0; +} + + /***************************************************************************** * @@ -122,6 +287,88 @@ static void DrawTrackAndEndPts( } + +static void RedrawSelectedTracksBoundary() +{ +/* Truth table: 4 cases for a track trk, connected to trk1 + * SELREDRAW + * trk, trk1: F, F - No changes, nothing to draw + * T, F - trk changes but trk1 didn't, flip drawing of select boundary marker + * F, T - trk didn't change but trk1 did, handle redrawing when we get to 2nd track + * T, T - both changed, but we don't need to redraw anything + * unfortunately we will do a redundant redraw when we get to the 2nd track + */ +// if (importTrack != NULL) +// return; + track_p trk; + TRK_ITERATE( trk ) { + if ( GetTrkBits(trk) & TB_SELREDRAW ) { + // This track has changed + for ( EPINX_T ep = 0; ep < GetTrkEndPtCnt(trk); ep++ ) { + track_p trk1 = GetTrkEndTrk( trk, ep ); + if ( trk1 == NULL ) + continue; + +// if ( GetTrkIndex( trk ) < GetTrkIndex( trk1 ) +// continue; + if ( ( GetTrkBits(trk1) & TB_SELREDRAW ) == 0 ) { + // Connected track hasn't changed + wDrawColor color = selectedColor; + if ( ( GetTrkBits(trk) & TB_SELECTED ) == ( GetTrkBits(trk1) & TB_SELECTED ) ) { + // There was a select boundary here, but not now. + // Undraw old X + color = wDrawColorWhite; + } + DIST_T len; + coOrd p = GetTrkEndPos( trk, ep ); + ANGLE_T a = GetTrkEndAngle( trk, ep ); + coOrd p0, p1, p2; + len = GetTrkGauge(trk)*2.0; + if (len < 0.10*mainD.scale) + len = 0.10*mainD.scale; + Translate( &p1, p, a+45, len ); + Translate( &p2, p, a+225, len ); + DrawLine( &mainD, p1, p2, 2, color ); + Translate( &p1, p, a-45, len ); + Translate( &p2, p, a-225, len ); + DrawLine( &mainD, p1, p2, 2, color ); + if ( color == wDrawColorWhite ) { + // Fill in holes by undraw cross + DIST_T len2 = sqrt( GetTrkGauge(trk)*GetTrkGauge(trk)/2.0 ); + DIST_T len3 = 0.1*mainD.scale; + color = GetTrkColor( trk, &mainD ); + if ( mainD.scale < twoRailScale ) { + Translate( &p0, p, a-225, len2 ); + Translate( &p1, p0, a, len3 ); + Translate( &p2, p0, a+180, len3 ); + DrawLine( &mainD, p1, p2, GetTrkWidth(trk), color ); + Translate( &p0, p, a+225, len2 ); + Translate( &p1, p0, a, len3 ); + Translate( &p2, p0, a+180, len3 ); + DrawLine( &mainD, p1, p2, GetTrkWidth(trk), color ); + color = GetTrkColor( trk1, &mainD ); + Translate( &p0, p, a-45, len2 ); + Translate( &p1, p0, a, len3 ); + Translate( &p2, p0, a+180, len3 ); + DrawLine( &mainD, p1, p2, GetTrkWidth(trk1), color ); + Translate( &p0, p, a+45, len2 ); + Translate( &p1, p0, a, len3 ); + Translate( &p2, p0, a+180, len3 ); + DrawLine( &mainD, p1, p2, GetTrkWidth(trk1), color ); + } else { + Translate( &p1, p, a, len3 ); + Translate( &p2, p, a+180, len3 ); + DrawLine( &mainD, p1, p2, GetTrkWidth(trk), color ); + } + } + } + } + ClrTrkBits( trk, TB_SELREDRAW ); + } + } +} + + EXPORT void SetAllTrackSelect( BOOL_T select ) { track_p trk; @@ -139,27 +386,26 @@ EXPORT void SetAllTrackSelect( BOOL_T select ) if (select) selectedTrackCount++; if ((GetTrkSelected(trk)!=0) != select) { - if (!doRedraw) - DrawTrackAndEndPts( trk, wDrawColorWhite ); if (select) SetTrkBits( trk, TB_SELECTED ); else ClrTrkBits( trk, TB_SELECTED ); if (!doRedraw) + SetTrkBits( trk, TB_SELREDRAW ); DrawTrackAndEndPts( trk, wDrawColorBlack ); } } } SelectedTrackCountChange(); if (doRedraw) { - MainRedraw(); - MapRedraw(); + MainRedraw(); // SetAllTrackSelect } else { + RedrawSelectedTracksBoundary(); wDrawDelayUpdate( mainD.d, FALSE ); } } -/* Invert selected state of all visible objects. +/* Invert selected state of all visible non-module objects. * * \param none * \return none @@ -171,21 +417,15 @@ EXPORT void InvertTrackSelect( void *ptr ) trk = NULL; while ( TrackIterate( &trk ) ) { - if (GetLayerVisible( GetTrkLayer( trk ))) { - if (GetTrkSelected(trk)) - { - ClrTrkBits( trk, TB_SELECTED ); - selectedTrackCount--; - } - else - SetTrkBits( trk, TB_SELECTED ); - selectedTrackCount++; + if (GetLayerVisible( GetTrkLayer( trk )) && + !GetLayerModule(GetTrkLayer( trk ))) { + SelectOneTrack( trk, GetTrkSelected(trk)==0 ); } } + RedrawSelectedTracksBoundary(); SelectedTrackCountChange(); - MainRedraw(); - MapRedraw(); + MainRedraw(); // InvertTrackSelect } /* Select orphaned (ie single) track pieces. @@ -204,7 +444,7 @@ EXPORT void OrphanedTrackSelect( void *ptr ) while( TrackIterate( &trk ) ) { cnt = 0; - if( GetLayerVisible( GetTrkLayer( trk ))) { + if( GetLayerVisible( GetTrkLayer( trk ) && !GetLayerModule(GetTrkLayer(trk)))) { for( ep = 0; ep < GetTrkEndPtCnt( trk ); ep++ ) { if( GetTrkEndTrk( trk, ep ) ) cnt++; @@ -217,17 +457,21 @@ EXPORT void OrphanedTrackSelect( void *ptr ) } } } + RedrawSelectedTracksBoundary(); SelectedTrackCountChange(); - MainRedraw(); - MapRedraw(); + MainRedraw(); // OrphanTrackSelect } - static void SelectOneTrack( track_p trk, wBool_t selected ) { - DrawTrackAndEndPts( trk, wDrawColorWhite ); + BOOL_T bRedraw = (GetTrkSelected(trk) != 0) != selected; + if ( !bRedraw ) { + ClrTrkBits( trk, TB_SELREDRAW ); + return; + } + SetTrkBits( trk, TB_SELREDRAW ); if (selected) { SetTrkBits( trk, TB_SELECTED ); selectedTrackCount++; @@ -240,8 +484,27 @@ static void SelectOneTrack( } +static void HighlightSelectedTracks( + track_p trk_ignore, BOOL_T box, BOOL_T invert ) +{ + track_p trk = NULL; + if ( selectedTrackCount == 0 ) + return; + while ( TrackIterate( &trk ) ) { + if (trk == trk_ignore) continue; + if(GetTrkSelected(trk)) { + if (!GetLayerVisible( GetTrkLayer( trk ))) continue; + if (invert) + DrawTrack(trk,&tempD,wDrawColorPreviewUnselected); + else + DrawTrack(trk,&tempD,wDrawColorPreviewSelected ); + } + } + +} + static void SelectConnectedTracks( - track_p trk ) + track_p trk, BOOL_T display_only ) { track_p trk1; int inx; @@ -249,32 +512,65 @@ static void SelectConnectedTracks( tlist_da.cnt = 0; TlistAppend( trk ); InfoCount( 0 ); - wDrawDelayUpdate( mainD.d, FALSE ); + if (!display_only) wDrawDelayUpdate( mainD.d, FALSE ); for (inx=0; inx<tlist_da.cnt; inx++) { - if ( inx > 0 && selectedTrackCount == 0 ) + if ( inx > 0 && (selectedTrackCount == 0) && !display_only ) return; trk = Tlist(inx); if (inx!=0 && - GetTrkSelected(trk)) + GetTrkSelected(trk)) { + if (display_only) + DrawTrack(trk,&tempD,wDrawColorPreviewSelected ); continue; + } else if (GetTrkSelected(trk)) { + if (display_only) + DrawTrack(trk,&tempD,wDrawColorPreviewUnselected); + continue; + } for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { trk1 = GetTrkEndTrk( trk, ep ); - if (trk1 && (!GetTrkSelected(trk1)) && GetLayerVisible( GetTrkLayer( trk1 )) ) { - TlistAppend( trk1 ) + if (trk1 && !TListSearch(trk1) && GetLayerVisible( GetTrkLayer( trk1 ))) { + if (GetTrkSelected(trk1)) { + if (display_only) DrawTrack(trk1,&tempD,wDrawColorPreviewSelected ); + } else TlistAppend( trk1 ); } } - if (!GetTrkSelected(trk)) { - SelectOneTrack( trk, TRUE ); - InfoCount( inx+1 ); + if (display_only) DrawTrack(trk,&tempD,wDrawColorPreviewSelected ); + else if (!GetTrkSelected(trk)) { + if (GetLayerModule(GetTrkLayer(trk))) { + continue; + } else { + SelectOneTrack( trk, TRUE ); + InfoCount( inx+1 ); + } } - SetTrkBits(trk, TB_SELECTED); } - wDrawDelayUpdate( mainD.d, TRUE ); - wFlush(); - InfoCount( trackCount ); + if (!display_only) { + RedrawSelectedTracksBoundary(); + wDrawDelayUpdate( mainD.d, TRUE ); + wFlush(); + InfoCount( trackCount ); + } } +typedef void (*doModuleTrackCallBack_t)(track_p, BOOL_T); +static int DoModuleTracks( int moduleLayer, doModuleTrackCallBack_t doit, BOOL_T val) +{ + track_p trk; + trk = NULL; + int cnt = 0; + while ( TrackIterate( &trk ) ) { + if (GetTrkLayer(trk) == moduleLayer) { + doit( trk, val ); + cnt++; + } + } + return cnt; +} +static void DrawSingleTrack(track_p trk, BOOL_T bit) { + DrawTrack(trk,&tempD,bit?wDrawColorPreviewSelected:wDrawColorPreviewUnselected); +} typedef BOOL_T (*doSelectedTrackCallBack_t)(track_p, BOOL_T); static void DoSelectedTracks( doSelectedTrackCallBack_t doit ) @@ -331,9 +627,41 @@ EXPORT void SelectTrackWidth( void* width ) UndoEnd(); } +EXPORT void SelectLineType( void* width ) +{ + track_p trk; + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount<=0) { + ErrorMessage( MSG_NO_SELECTED_TRK ); + return; + } + UndoStart( _("Change Line Type"), "linetype" ); + trk = NULL; + wDrawDelayUpdate( mainD.d, TRUE ); + while ( TrackIterate( &trk ) ) { + if (GetTrkSelected(trk)) { + UndoModify( trk ); + if (QueryTrack(trk, Q_CAN_MODIFY_CONTROL_POINTS)) + SetBezierLineType(trk, (int) (long) width); + else if (QueryTrack(trk, Q_IS_DRAW)) + SetLineType( trk, (int)(long)width ); + else if (QueryTrack(trk, Q_IS_STRUCTURE)) { + SetCompoundLineType(trk, (int)(long)width); + } + } + } + wDrawDelayUpdate( mainD.d, FALSE ); + UndoEnd(); +} + +static BOOL_T doingDouble; EXPORT void SelectDelete( void ) { + if (GetCurrentCommand() != selectCmdInx) return; + if (doingDouble) return; + if (SelectedTracksAreFrozen()) return; if (selectedTrackCount>0) { @@ -341,6 +669,7 @@ EXPORT void SelectDelete( void ) wDrawDelayUpdate( mainD.d, TRUE ); wDrawDelayUpdate( mapD.d, TRUE ); DoSelectedTracks( DeleteTrack ); + DoRedraw(); // SelectDelete wDrawDelayUpdate( mainD.d, FALSE ); wDrawDelayUpdate( mapD.d, FALSE ); selectedTrackCount = 0; @@ -368,8 +697,10 @@ static BOOL_T FlipHidden( track_p trk, BOOL_T junk ) if ( drawTunnel == 0 ) flipHiddenDoSelectRecount = TRUE; if (GetTrkVisible(trk)) { - ClrTrkBits( trk, TB_VISIBLE|(drawTunnel==0?TB_SELECTED:0) ); - } else { + ClrTrkBits( trk, TB_VISIBLE|(drawTunnel==0?(TB_SELECTED|TB_SELREDRAW):0) ); + ClrTrkBits (trk, TB_BRIDGE); + ClrTrkBits (trk, TB_NOTIES); +; } else { SetTrkBits( trk, TB_VISIBLE ); } /*DrawNewTrack( trk );*/ @@ -382,6 +713,29 @@ static BOOL_T FlipHidden( track_p trk, BOOL_T junk ) return TRUE; } +static BOOL_T FlipBridge( track_p trk, BOOL_T junk ) +{ + UndoModify( trk ); + if (GetTrkBridge(trk)) { + ClrTrkBits( trk, TB_BRIDGE ); + } else { + SetTrkBits( trk, TB_BRIDGE ); + SetTrkBits( trk, TB_VISIBLE); + } + return TRUE; +} + +static BOOL_T FlipTies( track_p trk, BOOL_T junk ) +{ + UndoModify( trk ); + if (GetTrkNoTies(trk)) { + ClrTrkBits( trk, TB_NOTIES ); + } else { + SetTrkBits( trk, TB_NOTIES ); + SetTrkBits( trk, TB_VISIBLE ); + } + return TRUE; +} EXPORT void SelectTunnel( void ) { @@ -401,6 +755,39 @@ EXPORT void SelectTunnel( void ) SelectRecount(); } +EXPORT void SelectBridge( void ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + flipHiddenDoSelectRecount = FALSE; + UndoStart( _("Bridge Tracks "), "bridge" ); + wDrawDelayUpdate( mainD.d, TRUE ); + DoSelectedTracks( FlipBridge ); + wDrawDelayUpdate( mainD.d, FALSE ); + UndoEnd(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } + MainRedraw(); // SelectBridge +} + +EXPORT void SelectTies( void ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + flipHiddenDoSelectRecount = FALSE; + UndoStart( _("Ties Tracks "), "noties" ); + wDrawDelayUpdate( mainD.d, TRUE ); + DoSelectedTracks( FlipTies ); + wDrawDelayUpdate( mainD.d, FALSE ); + UndoEnd(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } + MainRedraw(); // SelectTies +} void SelectRecount( void ) { @@ -445,6 +832,7 @@ EXPORT void SelectCurrentLayer( void ) SelectOneTrack( trk, TRUE ); } } + RedrawSelectedTracksBoundary(); } @@ -530,8 +918,7 @@ EXPORT void DoRefreshCompound( void ) DoSelectedTracks( RefreshCompound ); RefreshCompound( NULL, FALSE ); UndoEnd(); - MainRedraw(); - MapRedraw(); + MainRedraw(); // DoRefreshCompound } else { ErrorMessage( MSG_NO_SELECTED_TRK ); } @@ -539,15 +926,12 @@ EXPORT void DoRefreshCompound( void ) static drawCmd_t tempSegsD = { - NULL, &tempSegDrawFuncs, DC_GROUP, 1, 0.0, {0.0, 0.0}, {0.0, 0.0}, Pix2CoOrd, CoOrd2Pix }; + NULL, &tempSegDrawFuncs, 0, 1, 0.0, {0.0, 0.0}, {0.0, 0.0}, Pix2CoOrd, CoOrd2Pix }; EXPORT void WriteSelectedTracksToTempSegs( void ) { track_p trk; - long oldOptions; DYNARR_RESET( trkSeg_t, tempSegs_da ); tempSegsD.dpi = mainD.dpi; - oldOptions = tempSegDrawFuncs.options; - tempSegDrawFuncs.options = wDrawOptTemp; for ( trk=NULL; TrackIterate(&trk); ) { if ( GetTrkSelected( trk ) ) { if ( IsTrack( trk ) ) @@ -557,7 +941,6 @@ EXPORT void WriteSelectedTracksToTempSegs( void ) SetTrkBits( trk, TB_SELECTED ); } } - tempSegDrawFuncs.options = oldOptions; } static char rescaleFromScale[20]; @@ -619,6 +1002,7 @@ static BOOL_T RescaleDoIt( track_p trk, BOOL_T junk ) { EPINX_T ep, ep1; track_p trk1; + UndrawNewTrack( trk ); UndoModify(trk); if ( rescalePercent != 100.0 ) { for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { @@ -636,6 +1020,7 @@ static BOOL_T RescaleDoIt( track_p trk, BOOL_T junk ) if ( rescaleMode==0 ) SetTrkScale( trk, rescaleToInx ); getboundsCount++; + DrawNewTrack( trk ); return TRUE; } @@ -688,7 +1073,6 @@ static void RescaleDlgOk( rescaleToInx = GetScaleInx( rescaleToScaleInx, rescaleToGaugeInx ); DoSelectedTracks( RescaleDoIt ); - DoRedraw(); wHide( rescalePG.win ); } @@ -799,38 +1183,6 @@ EXPORT void DoRescale( void ) wShow( rescalePG.win ); } - - -#define MOVE_NORMAL (0) -#define MOVE_FAST (1) -#define MOVE_QUICK (2) -static char *quickMoveMsgs[] = { - N_("Draw moving track normally"), - N_("Draw moving track simply"), - N_("Draw moving track as end-points") }; -static wMenuToggle_p quickMove1M[3]; -static wMenuToggle_p quickMove2M[3]; - -static void ChangeQuickMove( wBool_t set, void * mode ) -{ - long inx; - quickMove = (long)mode; - InfoMessage( quickMoveMsgs[quickMove] ); - DoChangeNotification( CHANGE_CMDOPT ); - for (inx = 0; inx<3; inx++) { - wMenuToggleSet( quickMove1M[inx], quickMove == inx ); - wMenuToggleSet( quickMove2M[inx], quickMove == inx ); - } -} - -EXPORT void UpdateQuickMove( void * junk ) -{ - long inx; - for (inx = 0; inx<3; inx++) { - wMenuToggleSet( quickMove1M[inx], quickMove == inx ); - wMenuToggleSet( quickMove2M[inx], quickMove == inx ); - } -} static void DrawSelectedTracksD( drawCmd_p d, wDrawColor color ) @@ -846,7 +1198,11 @@ static void DrawSelectedTracksD( drawCmd_p d, wDrawColor color ) if ( OFF_D( d->orig, d->size, lo, hi ) ) continue; } + if (color != wDrawColorWhite) + ClrTrkBits(trk, TB_UNDRAWN); DrawTrack( trk, d, color ); + if (color == wDrawColorWhite) + SetTrkBits( trk, TB_UNDRAWN ); } /*wDrawDelayUpdate( d->d, FALSE );*/ } @@ -865,7 +1221,7 @@ static ANGLE_T moveAngle; static coOrd moveD_hi, moveD_lo; static drawCmd_t moveD = { - NULL, &tempDrawFuncs, DC_SIMPLE, 1, 0.0, {0.0, 0.0}, {0.0, 0.0}, Pix2CoOrd, CoOrd2Pix }; + NULL, &tempSegDrawFuncs, DC_SIMPLE, 1, 0.0, {0.0, 0.0}, {0.0, 0.0}, Pix2CoOrd, CoOrd2Pix }; @@ -884,61 +1240,56 @@ static void AccumulateTracks( void ) coOrd lo, hi; /*wDrawDelayUpdate( moveD.d, TRUE );*/ - if (quickMove == MOVE_FAST) - moveD.options |= DC_QUICK; - for ( inx = 0; inx<tlist_da.cnt; inx++ ) { - trk = tlist2[inx]; - if (trk) { - GetBoundingBox( trk, &hi, &lo ); - if (lo.x <= moveD_hi.x && hi.x >= moveD_lo.x && - lo.y <= moveD_hi.y && hi.y >= moveD_lo.y ) { - if (quickMove != MOVE_QUICK) { -#if defined(WINDOWS) && ! defined(WIN32) - if ( tempSegs_da.cnt+100 > 65500 / sizeof(*(trkSeg_p)NULL) ) { - ErrorMessage( MSG_TOO_MANY_SEL_TRKS ); - - quickMove = MOVE_QUICK; - } else -#endif - DrawTrack( trk, &moveD, wDrawColorBlack ); - } - tlist2[inx] = NULL; - movedCnt++; + movedCnt =0; + for ( inx = 0; inx<tlist_da.cnt; inx++ ) { + trk = Tlist(inx); + if (trk) { + GetBoundingBox( trk, &hi, &lo ); + if (lo.x <= moveD_hi.x && hi.x >= moveD_lo.x && + lo.y <= moveD_hi.y && hi.y >= moveD_lo.y ) { + if (!QueryTrack(trk,Q_IS_CORNU)) + DrawTrack( trk, &moveD, wDrawColorBlack ); } + movedCnt++; } - } - moveD.options &= ~DC_QUICK; + } InfoCount( movedCnt ); /*wDrawDelayUpdate( moveD.d, FALSE );*/ } +static void AddEndCornus() { + for (int i=0;i<tlist_da.cnt;i++) { + track_p trk = DYNARR_N(track_p,tlist_da,i); + track_p tc; + for (int j=GetTrkEndPtCnt(trk)-1;j>=0;j--) { + tc = GetTrkEndTrk(trk,j); + if (tc && !GetTrkSelected(tc) && QueryTrack(tc,Q_IS_CORNU) && !QueryTrack(trk,Q_IS_CORNU)) { //On end and cornu + SelectOneTrack( tc, TRUE ); + DYNARR_APPEND(track_p,tlist_da,1); //Add to selected list + DYNARR_LAST(track_p,tlist_da) = tc; + } + } + } +} + static void GetMovedTracks( BOOL_T undraw ) { - wSetCursor( wCursorWait ); + wSetCursor( mainD.d, wCursorWait ); DYNARR_RESET( track_p, tlist_da ); DoSelectedTracks( AddSelectedTrack ); - tlist2 = (track_p*)MyRealloc( tlist2, (tlist_da.cnt+1) * sizeof *(track_p*)0 ); - if (tlist_da.ptr) - memcpy( tlist2, tlist_da.ptr, (tlist_da.cnt) * sizeof *(track_p*)0 ); - tlist2[tlist_da.cnt] = NULL; + AddEndCornus(); //Include Cornus that are attached at ends of selected DYNARR_RESET( trkSeg_p, tempSegs_da ); - moveD = mainD; - moveD.funcs = &tempSegDrawFuncs; - moveD.options = DC_SIMPLE; - tempSegDrawFuncs.options = wDrawOptTemp; moveOrig = mainD.orig; movedCnt = 0; InfoCount(0); - wSetCursor( wCursorNormal ); + wSetCursor( mainD.d, defaultCursor ); moveD_hi = moveD_lo = mainD.orig; moveD_hi.x += mainD.size.x; moveD_hi.y += mainD.size.y; AccumulateTracks(); if (undraw) { DrawSelectedTracksD( &mainD, wDrawColorWhite ); - /*DrawSegs( &mainD, zero, 0.0, &tempSegs(0), tempSegs_da.cnt, - trackGauge, wDrawColorBlack );*/ } } @@ -989,48 +1340,50 @@ static void DrawMovedTracks( void ) { int inx; track_p trk; - track_p other; - EPINX_T i; - coOrd pos; - wDrawBitMap_p bm; - ANGLE_T a; - int ia; - - if ( quickMove != MOVE_QUICK) { - DrawSegs( &tempD, moveOrig, moveAngle, &tempSegs(0), tempSegs_da.cnt, - 0.0, wDrawColorBlack ); - return; - } + dynArr_t cornu_segs; + + DrawSegs( &tempD, moveOrig, moveAngle, &tempSegs(0), tempSegs_da.cnt, + 0.0, wDrawColorBlack ); + for ( inx=0; inx<tlist_da.cnt; inx++ ) { trk = Tlist(inx); - if (tlist2[inx] != NULL) - continue; - for (i=GetTrkEndPtCnt(trk)-1; i>=0; i--) { - pos = GetTrkEndPos(trk,i); - if (!move0B) { - Rotate( &pos, zero, moveAngle ); - } - pos.x += moveOrig.x; - pos.y += moveOrig.y; - if ((other=GetTrkEndTrk(trk,i)) == NULL || - !GetTrkSelected(other)) { - bm = endpt_bm; - } else if (other != NULL && GetTrkIndex(trk) < GetTrkIndex(other)) { - a = GetTrkEndAngle(trk,i)+22.5; - if (!move0B) - a += moveAngle; - a = NormalizeAngle( a ); - if (a>=180.0) - a -= 180.0; - ia = (int)(a/45.0); - bm = angle_bm[ia]; - } else { - continue; + if (QueryTrack(trk,Q_IS_CORNU)) { + DYNARR_RESET(trkSeg_t,cornu_segs); + coOrd pos[2]; + DIST_T radius[2]; + ANGLE_T angle[2]; + coOrd center[2]; + trackParams_t trackParams; + if (GetTrackParams(PARAMS_CORNU, trk, zero, &trackParams)) { + for (int i=0;i<2;i++) { + pos[i] = trackParams.cornuEnd[i]; + center[i] = trackParams.cornuCenter[i]; + angle[i] = trackParams.cornuAngle[i]; + radius[i] = trackParams.cornuRadius[i]; + if (!GetTrkEndTrk(trk,i) || + (GetTrkEndTrk(trk,i) && GetTrkSelected(GetTrkEndTrk(trk,i)))) { + if (!move0B) { + Rotate( &pos[i], zero, moveAngle ); + Rotate( ¢er[i],zero, moveAngle ); + angle[i] = NormalizeAngle(angle[i]+moveAngle); + } + pos[i].x += moveOrig.x; + pos[i].y += moveOrig.y; + center[i].x +=moveOrig.x; + center[i].y +=moveOrig.y; + } + } + CallCornu0(&pos[0],¢er[0],&angle[0],&radius[0],&cornu_segs, FALSE); + trkSeg_p cornu_p = &DYNARR_N(trkSeg_t,cornu_segs,0); + + DrawSegsO(&tempD, trk, zero, 0.0, cornu_p,cornu_segs.cnt, + GetTrkGauge(trk), wDrawColorBlack, DTS_LEFT|DTS_RIGHT ); } - if ( !OFF_MAIND( pos, pos ) ) - DrawBitMap( &tempD, pos, bm, selectedColor ); + } + } + return; } @@ -1041,7 +1394,8 @@ static void MoveTracks( BOOL_T rotate, coOrd base, coOrd orig, - ANGLE_T angle ) + ANGLE_T angle, + BOOL_T undo) { track_p trk, trk1; EPINX_T ep, ep1; @@ -1051,48 +1405,47 @@ static void MoveTracks( DIST_T endRadius; coOrd endCenter; - wSetCursor( wCursorWait ); + wSetCursor( mainD.d, wCursorWait ); /*UndoStart( "Move/Rotate Tracks", "move/rotate" );*/ if (tlist_da.cnt <= incrementalDrawLimit) { - DrawMapBoundingBox( FALSE ); - if (eraseFirst) + if (eraseFirst) { DrawSelectedTracksD( &mainD, wDrawColorWhite ); - DrawSelectedTracksD( &mapD, wDrawColorWhite ); + DrawSelectedTracksD( &mapD, wDrawColorWhite ); + } } for ( inx=0; inx<tlist_da.cnt; inx++ ) { trk = Tlist(inx); UndoModify( trk ); - if (move) - MoveTrack( trk, base ); - if (rotate) - RotateTrack( trk, orig, angle ); - for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { - if ((trk1 = GetTrkEndTrk(trk,ep)) != NULL && - !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! + BOOL_T fixed_end; + fixed_end = FALSE; + if (QueryTrack(trk, Q_IS_CORNU)) { + for (int i=0;i<2;i++) { + track_p te; + if ((te = GetTrkEndTrk(trk,i)) && !GetTrkSelected(te)) { + fixed_end = TRUE; + } + } + } + + if (!fixed_end) { + if (move) + MoveTrack( trk, base ); + if (rotate) + RotateTrack( trk, orig, angle ); + for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { + if ((trk1 = GetTrkEndTrk(trk,ep)) != NULL && + !GetTrkSelected(trk1)) { + ep1 = GetEndPtConnectedToMe( trk1, trk ); + DisconnectTracks( trk, ep, trk1, ep1 ); + DrawEndPt( &mainD, trk1, ep1, wDrawColorBlack ); + } + } + } else { + if (QueryTrack(trk, Q_IS_CORNU)) { //Cornu will be at the end of selected set + for (int i=0;i<2;i++) { + if ((trk1 = GetTrkEndTrk(trk,i)) && GetTrkSelected(trk1)) { + ep1 = GetEndPtConnectedToMe( trk1, trk ); + DisconnectTracks(trk,i,trk1,ep1); GetTrackParams(PARAMS_CORNU,trk1,GetTrkEndPos(trk1,ep1),&trackParms); if (trackParms.type == curveTypeStraight) { endRadius = 0; @@ -1102,39 +1455,55 @@ static void MoveTracks( endCenter = trackParms.arcP; } DrawTrack(trk,&mainD,wDrawColorWhite); - DrawTrack(trk1,&mapD,wDrawColorWhite); + DrawTrack(trk,&mapD,wDrawColorWhite); endAngle = NormalizeAngle(GetTrkEndAngle(trk1,ep1)+180); - if (SetCornuEndPt(trk,ep,GetTrkEndPos(trk1,ep1),endCenter,endAngle,endRadius)) { - ConnectTracks(trk,ep,trk1,ep1); + if (SetCornuEndPt(trk,i,GetTrkEndPos(trk1,ep1),endCenter,endAngle,endRadius)) { + ConnectTracks(trk,i,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); + DeleteTrack(trk,TRUE); + ErrorMessage(_("Cornu too tight - it was deleted")); + DoRedraw(); // MoveTracks: Cornu/delete + return; + } + } else if (!trk1) { //No end track + DrawTrack(trk,&mainD,wDrawColorWhite); + DrawTrack(trk,&mapD,wDrawColorWhite); + GetTrackParams(PARAMS_CORNU,trk,GetTrkEndPos(trk,i),&trackParms); + if (move) { + coOrd end_pos, end_center; + end_pos = trackParms.cornuEnd[i]; + end_pos.x += base.x; + end_pos.y += base.y; + end_center = trackParms.cornuCenter[i]; + end_center.x += base.x; + end_center.y += base.y; + SetCornuEndPt(trk,i,end_pos,end_center,trackParms.cornuAngle[i],trackParms.cornuRadius[i]); + } + if (rotate) { + coOrd end_pos, end_center; + ANGLE_T end_angle; + end_pos = trackParms.cornuEnd[i]; + end_center = trackParms.cornuCenter[i]; + Rotate(&end_pos, orig, angle); + Rotate(&end_center, orig, angle); + end_angle = NormalizeAngle( trackParms.cornuAngle[i] + angle ); + SetCornuEndPt(trk,i,end_pos,end_center,end_angle,trackParms.cornuRadius[i]); } + DrawTrack(trk,&mainD,wDrawColorBlack); + DrawTrack(trk,&mapD,wDrawColorBlack); } } - DrawEndPt( &mainD, trk1, ep1, wDrawColorBlack ); } - } + } InfoCount( inx ); -#ifdef LATER - if (tlist_da.cnt <= incrementalDrawLimit) - DrawNewTrack( trk ); -#endif - } - if (tlist_da.cnt > incrementalDrawLimit) { - DoRedraw(); - } else { - DrawSelectedTracksD( &mainD, wDrawColorBlack ); - DrawSelectedTracksD( &mapD, wDrawColorBlack ); - DrawMapBoundingBox( TRUE ); } - wSetCursor( wCursorNormal ); - UndoEnd(); - tempSegDrawFuncs.options = 0; + ClrAllTrkBits(TB_UNDRAWN); + DoRedraw(); + wSetCursor( mainD.d, defaultCursor ); + if (undo) UndoEnd(); InfoCount( trackCount ); } @@ -1159,7 +1528,7 @@ void MoveToJoin( angle += 180.0; angle = NormalizeAngle( angle ); GetMovedTracks( FALSE ); - MoveTracks( TRUE, TRUE, TRUE, base, orig, angle ); + MoveTracks( TRUE, TRUE, TRUE, base, orig, angle, TRUE ); UndrawNewTrack( trk0 ); UndrawNewTrack( trk1 ); ConnectTracks( trk0, ep0, trk1, ep1 ); @@ -1176,6 +1545,145 @@ void FreeTempStrings() { } } } + + +wBool_t FindEndIntersection(coOrd base, coOrd orig, ANGLE_T angle, track_p * t1, EPINX_T * ep1, track_p * t2, EPINX_T * ep2) { + *ep1 = -1; + *ep2 = -1; + *t1 = NULL; + *t2 = NULL; + for ( int inx=0; inx<tlist_da.cnt; inx++ ) { //All selected + track_p ts = Tlist(inx); + for (int i=0; i<GetTrkEndPtCnt(ts); i++) { //All EndPoints + track_p ct; + if ((ct = GetTrkEndTrk(ts,i))!=NULL) { + if (GetTrkSelected(ct) || QueryTrack(ts,Q_IS_CORNU)) continue; // Another selected track or Cornu - ignore + } + + coOrd pos1 = GetTrkEndPos(ts,i); + if (angle != 0.0) + Rotate(&pos1,orig,angle); + else { + pos1.x +=base.x; + pos1.y +=base.y; + } + coOrd pos2; + pos2 = pos1; + track_p tt; + if ((tt=OnTrackIgnore(&pos2,FALSE,TRUE,ts))!=NULL) { + if (GetTrkGauge(ts) != GetTrkGauge(tt)) continue; //Ignore if different gauges + if (!GetTrkSelected(tt)) { //Ignore if new track is selected + EPINX_T epp = PickUnconnectedEndPointSilent(pos2, tt); + if (epp>=0) { + DIST_T d = FindDistance(pos1,GetTrkEndPos(tt,epp)); + if (IsClose(d)) { + *ep1 = epp; + *ep2 = i; + *t1 = tt; + *t2 = ts; + return TRUE; + } + } else { + epp = PickEndPoint(pos2,tt); //Any close end point (even joined) + if (epp>=0) { + ct = GetTrkEndTrk(tt,epp); + if (ct && GetTrkSelected(ct)) { //Point is junction to selected track - so will be broken + DIST_T d = FindDistance(pos1,GetTrkEndPos(tt,epp)); + if (IsClose(d)) { + *ep1 = epp; + *ep2 = i; + *t1 = tt; + *t2 = ts; + return TRUE; + } + } + } + } + } + } + } + } + return FALSE; +} + +void DrawHighlightLayer(int layer) { + track_p ts = NULL; + BOOL_T initial = TRUE; + coOrd layer_hi = zero,layer_lo = zero; + while ( TrackIterate( &ts ) ) { + if ( !GetLayerVisible( GetTrkLayer( ts))) continue; + if (!GetTrkSelected(ts)) continue; + if (GetTrkLayer(ts) != layer) continue; + coOrd hi,lo; + GetBoundingBox(ts, &hi, &lo); + if (initial) { + layer_hi = hi; + layer_lo = lo; + initial = FALSE; + } else { + if (layer_hi.x < hi.x ) layer_hi.x = hi.x; + if (layer_hi.y < hi.y ) layer_hi.y = hi.y; + if (layer_lo.x > lo.x ) layer_lo.x = lo.x; + if (layer_lo.y > lo.y ) layer_lo.y = lo.y; + } + } + wPos_t margin = (wPos_t)(10.5*mainD.scale/mainD.dpi); + layer_hi.x +=margin; + layer_hi.y +=margin; + layer_lo.x -=margin; + layer_lo.y -=margin; + + wPos_t rect[4][2]; + int type[4]; + coOrd top_left, bot_right; + top_left.x = layer_lo.x; top_left.y = layer_hi.y; + bot_right.x = layer_hi.x; bot_right.y = layer_lo.y; + type[0] = type[1] = type[2] = type[3] = 0; + mainD.CoOrd2Pix(&mainD,layer_lo,&rect[0][0],&rect[0][1]); + mainD.CoOrd2Pix(&mainD,top_left,&rect[1][0],&rect[1][1]); + mainD.CoOrd2Pix(&mainD,layer_hi,&rect[2][0],&rect[2][1]); + mainD.CoOrd2Pix(&mainD,bot_right,&rect[3][0],&rect[3][1]); + wDrawPolygon(tempD.d,rect,(wPolyLine_e *)type,4,wDrawColorPowderedBlue,0,wDrawLineDash,wDrawOptTemp,0,0); +} + +void SetUpMenu2(coOrd pos, track_p trk) { + wMenuPushEnable( menuPushModify,FALSE); + wMenuPushEnable(descriptionMI,FALSE); + wMenuPushEnable( rotateAlignMI, FALSE ); + wMenuPushEnable( hideMI, FALSE ); + wMenuPushEnable( bridgeMI, FALSE ); + wMenuPushEnable( tiesMI, FALSE ); + 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(pos, trackParams.ttcenter); + if (dist < trackParams.ttradius/4) { + cmdMenuPos = trackParams.ttcenter; + } + } + } + if (trk && !QueryTrack( trk, Q_IS_DRAW )) { + wMenuPushEnable( hideMI, TRUE ); + wMenuPushEnable( bridgeMI, TRUE ); + wMenuPushEnable( tiesMI, TRUE ); + } + if (trk) { + wMenuPushEnable( menuPushModify, + (QueryTrack( trk, Q_CAN_MODIFY_CONTROL_POINTS ) || + QueryTrack( trk, Q_IS_CORNU ) || + (QueryTrack( trk, Q_IS_DRAW ) && !QueryTrack( trk, Q_IS_TEXT )) || + QueryTrack( trk, Q_IS_ACTIVATEABLE))); + } + if ((trk)) { + wMenuPushEnable(descriptionMI, QueryTrack( trk, Q_HAS_DESC )); + moveDescTrk = trk; + moveDescPos = pos; + } + if (selectedTrackCount>0) + wMenuPushEnable( rotateAlignMI, TRUE ); +} + static STATUS_T CmdMove( wAction_t action, @@ -1185,9 +1693,16 @@ static STATUS_T CmdMove( static coOrd orig; static int state; - switch( action&0xFF) { + static EPINX_T ep1; + static EPINX_T ep2; + static track_p t1; + static track_p t2; + static BOOL_T doingMove; + + switch( action & 0xFF) { case C_START: + DYNARR_RESET(trkSeg_t,anchors_da); if (selectedTrackCount == 0) { ErrorMessage( MSG_NO_SELECTED_TRK ); return C_TERMINATE; @@ -1197,63 +1712,123 @@ static STATUS_T CmdMove( } InfoMessage( _("Drag to move selected tracks - Shift+Ctrl+Arrow micro-steps the move") ); state = 0; + ep1 = -1; + ep2 = -1; + doingMove = FALSE; + break; + + case wActionMove: + DYNARR_RESET(trkSeg_t,anchors_da); + CreateMoveAnchor(pos); break; case C_DOWN: + DYNARR_RESET(trkSeg_t,anchors_da); + if (doingMove) { + doingMove = FALSE; + UndoEnd(); + } + if (SelectedTracksAreFrozen()) { return C_TERMINATE; } UndoStart( _("Move Tracks"), "move" ); base = zero; orig = pos; - GetMovedTracks(quickMove != MOVE_QUICK); + + GetMovedTracks(TRUE); SetMoveD( TRUE, base, 0.0 ); - //DrawMovedTracks(); drawCount = 0; state = 1; - MainRedraw(); - MapRedraw(); return C_CONTINUE; case C_MOVE: + DYNARR_RESET(trkSeg_t,anchors_da); + ep1=-1; + ep2=-1; drawEnable = enableMoveDraw; - //DrawMovedTracks(); base.x = pos.x - orig.x; base.y = pos.y - orig.y; SnapPos( &base ); SetMoveD( TRUE, base, 0.0 ); - //DrawMovedTracks(); + if (((MyGetKeyState()&(WKEY_ALT)) == 0) == magneticSnap) { // ALT + if (FindEndIntersection(base,zero,0.0,&t1,&ep1,&t2,&ep2)) { + coOrd pos2 = GetTrkEndPos(t2,ep2); + pos2.x +=base.x; + pos2.y +=base.y; + CreateEndAnchor(pos2,FALSE); + CreateEndAnchor(GetTrkEndPos(t1,ep1),TRUE); + } + } #ifdef DRAWCOUNT InfoMessage( " [%s %s] #%ld", FormatDistance(base.x), FormatDistance(base.y), drawCount ); #else InfoMessage( " [%s %s]", FormatDistance(base.x), FormatDistance(base.y) ); #endif drawEnable = TRUE; - MainRedraw(); - MapRedraw(); return C_CONTINUE; case C_UP: + DYNARR_RESET(trkSeg_t,anchors_da); state = 0; - //DrawMovedTracks(); FreeTempStrings(); - MoveTracks( quickMove==MOVE_QUICK, TRUE, FALSE, base, zero, 0.0 ); + if (t1 && ep1>=0 && t2 && ep2>=0) { + MoveToJoin(t2,ep2,t1,ep1); + } else { + MoveTracks( FALSE, TRUE, FALSE, base, zero, 0.0, TRUE ); + } + ep1 = -1; + ep2 = -1; + tlist_da.cnt = 0; return C_TERMINATE; case C_CMDMENU: - wMenuPopupShow( selectPopup1M ); + if (doingMove) UndoEnd(); + doingMove = FALSE; + 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; + } + } + } + moveDescPos = pos; + moveDescTrk = trk; + SetUpMenu2(pos,trk); + menuPos = pos; + wMenuPopupShow( selectPopup2M ); return C_CONTINUE; + case C_TEXT: + if ((action>>8) == 'c') { + panCenter = pos; + LOG( log_pan, 2, ( "PanCenter:Sel-%d %0.3f %0.3f\n", __LINE__, panCenter.x, panCenter.y ) ); + PanHere((void*)0); + } + if ((action>>8) == 'e') { + DoZoomExtents(0); + } + if ((action>>8) == '0' || (action>>8 == 'o')) { + PanMenuEnter('o'); + } + break; case C_REDRAW: /* DO_REDRAW */ + if (anchors_da.cnt) + DrawSegs( &tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack ); if ( state == 0 ) break; - DrawSelectedTracksD( &mainD, wDrawColorWhite ); DrawMovedTracks(); + break; case wActionExtKey: if (state) return C_CONTINUE; if (SelectedTracksAreFrozen()) return C_TERMINATE; if ((MyGetKeyState() & - (WKEY_SHIFT | WKEY_CTRL)) == (WKEY_SHIFT | WKEY_CTRL)) { + (WKEY_SHIFT | WKEY_CTRL)) == (WKEY_SHIFT | WKEY_CTRL)) { //Both base = zero; DIST_T w = tempD.scale/tempD.dpi; switch((wAccelKey_e) action>>8) { @@ -1275,21 +1850,35 @@ static STATUS_T CmdMove( } drawEnable = enableMoveDraw; - GetMovedTracks(quickMove!=MOVE_QUICK); - UndoStart( _("Move Tracks"), "move" ); + GetMovedTracks(TRUE); + if (!doingMove) UndoStart( _("Move Tracks"), "move" ); + doingMove = TRUE; SetMoveD( TRUE, base, 0.0 ); - DrawSelectedTracksD( &mainD, wDrawColorWhite ); - MoveTracks( quickMove==MOVE_QUICK, TRUE, FALSE, base, zero, 0.0 ); + MoveTracks( FALSE, TRUE, FALSE, base, zero, 0.0, FALSE ); ++microCount; if (microCount>5) { microCount = 0; - MainRedraw(); - MapRedraw(); + MainRedraw(); // Micro step move } return C_CONTINUE; } break; + case C_FINISH: + if (doingMove) { + doingMove = FALSE; + UndoEnd(); + } + tlist_da.cnt = 0; + break; + case C_CONFIRM: + case C_CANCEL: + if (doingMove) { + doingMove = FALSE; + UndoUndo(); + } + tlist_da.cnt = 0; + break; default: break; } @@ -1297,13 +1886,18 @@ static STATUS_T CmdMove( } -wMenuPush_p rotateAlignMI; -int rotateAlignState = 0; -static void RotateAlign( void ) +static int rotateAlignState = 0; + +static void RotateAlign( BOOL_T align ) { - rotateAlignState = 1; - InfoMessage( _("Click on selected object to align") ); + rotateAlignState = 0; + if (align) { + rotateAlignState = 1; + doingAlign = TRUE; + mode = MOVE; + InfoMessage( _("Align: Click on a selected object to be aligned") ); + } } static STATUS_T CmdRotate( @@ -1311,18 +1905,27 @@ static STATUS_T CmdRotate( coOrd pos ) { static coOrd base; + static coOrd orig_base; static coOrd orig; static ANGLE_T angle; static BOOL_T drawnAngle; static ANGLE_T baseAngle; + static BOOL_T clockwise; + static BOOL_T direction_set; static track_p trk; ANGLE_T angle1; coOrd pos1; static int state; + static EPINX_T ep1; + static EPINX_T ep2; + static track_p t1; + static track_p t2; + switch( action ) { case C_START: + DYNARR_RESET(trkSeg_t,anchors_da); state = 0; if (selectedTrackCount == 0) { ErrorMessage( MSG_NO_SELECTED_TRK ); @@ -1334,8 +1937,15 @@ static STATUS_T CmdRotate( InfoMessage( _("Drag to rotate selected tracks, Shift+RightClick for QuickRotate Menu") ); wMenuPushEnable( rotateAlignMI, TRUE ); rotateAlignState = 0; + ep1 = -1; + ep2 = -1; + break; + case wActionMove: + DYNARR_RESET(trkSeg_t,anchors_da); + CreateRotateAnchor(pos); break; case C_DOWN: + DYNARR_RESET(trkSeg_t,anchors_da); state = 1; if (SelectedTracksAreFrozen()) { return C_TERMINATE; @@ -1357,12 +1967,15 @@ static STATUS_T CmdRotate( } } } - GetMovedTracks(FALSE); + CreateRotateAnchor(orig); + GetMovedTracks(TRUE); SetMoveD( FALSE, base, angle ); + /*DrawLine( &mainD, base, orig, 0, wDrawColorBlack ); DrawMovedTracks(FALSE, orig, angle);*/ } else { pos1 = pos; + drawnAngle = FALSE; onTrackInSplit = TRUE; trk = OnTrack( &pos, TRUE, FALSE ); onTrackInSplit = FALSE; @@ -1396,13 +2009,13 @@ static STATUS_T CmdRotate( } GetMovedTracks(TRUE); SetMoveD( FALSE, orig, angle ); - //DrawMovedTracks(); } } - MainRedraw(); - MapRedraw(); return C_CONTINUE; case C_MOVE: + DYNARR_RESET(trkSeg_t,anchors_da); + ep1=-1; + ep2=-1; if ( rotateAlignState == 1 ) return C_CONTINUE; if ( rotateAlignState == 2 ) { @@ -1416,7 +2029,6 @@ static STATUS_T CmdRotate( ErrorMessage( MSG_2ND_TRACK_MUST_BE_UNSELECTED ); return C_CONTINUE; } - //DrawMovedTracks(); angle1 = NormalizeAngle( GetAngleAtPoint( trk, pos, NULL, NULL ) ); angle = NormalizeAngle(angle1-baseAngle); if ( angle > 90 && angle < 270 ) @@ -1427,65 +2039,95 @@ static STATUS_T CmdRotate( InfoMessage( _("Angle %0.3f"), angle1 ); SetMoveD( FALSE, orig, angle ); /*printf( "angle 2 = %0.3f\n", angle );*/ - //DrawMovedTracks(); - MainRedraw(); - MapRedraw(); return C_CONTINUE; } - if ( FindDistance( orig, pos ) > (6.0/75.0)*mainD.scale ) { - drawEnable = enableMoveDraw; - if (drawnAngle) { - DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); - DrawMovedTracks(); - } else if (quickMove != MOVE_QUICK) { - DrawSelectedTracksD( &mainD, wDrawColorWhite ); - } + ANGLE_T diff_angle = 0.0; + base = pos; + drawEnable = enableMoveDraw; + if ( FindDistance( orig, pos ) > (20.0/75.0)*mainD.scale ) { + ANGLE_T old_angle = angle; angle = FindAngle( orig, pos ); if (!drawnAngle) { baseAngle = angle; drawnAngle = TRUE; + direction_set = FALSE; + } else { + if (!direction_set) { + if (DifferenceBetweenAngles(baseAngle,angle)>=0) clockwise = TRUE; + else clockwise = FALSE; + direction_set = TRUE; + } else { + if (clockwise) { + if (DifferenceBetweenAngles(baseAngle,angle)<0 && fabs(DifferenceBetweenAngles(baseAngle, old_angle))<5) + clockwise = FALSE; + } else { + if (DifferenceBetweenAngles(baseAngle,angle)>=0 && fabs(DifferenceBetweenAngles(baseAngle,old_angle))<5) + clockwise = TRUE; + } + } } - base = pos; - angle = NormalizeAngle( angle-baseAngle ); - if ( MyGetKeyState()&WKEY_CTRL ) { - angle = NormalizeAngle(floor((angle+7.5)/15.0)*15.0); - Translate( &base, orig, angle+baseAngle, FindDistance(orig,pos) ); + orig_base = base = pos; + //angle = NormalizeAngle( angle-baseAngle ); + diff_angle = DifferenceBetweenAngles(baseAngle,angle); + if ( (MyGetKeyState() & (WKEY_CTRL|WKEY_SHIFT)) == (WKEY_CTRL|WKEY_SHIFT) ) { //Both Shift+Ctrl + if (clockwise) { + if (diff_angle<0) diff_angle+=360; + } else { + if (diff_angle>0) diff_angle-=360; + } + diff_angle = floor((diff_angle+7.5)/15.0)*15.0; + angle = baseAngle+diff_angle; } - DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); - SetMoveD( FALSE, orig, angle ); - //DrawMovedTracks(); + Translate( &base, orig, angle, FindDistance(orig,pos) ); //Line one + Translate( &orig_base,orig, baseAngle, FindDistance(orig,pos)<=(60.0/75.00*mainD.scale)?FindDistance(orig,pos):60.0/75.00*mainD.scale ); //Line two + SetMoveD( FALSE, orig, NormalizeAngle( angle-baseAngle ) ); + if (((MyGetKeyState()&(WKEY_ALT)) == WKEY_ALT) != magneticSnap) { //Just Shift + if (FindEndIntersection(zero,orig,NormalizeAngle( angle-baseAngle ),&t1,&ep1,&t2,&ep2)) { + coOrd pos2 = GetTrkEndPos(t2,ep2); + coOrd pos1 = GetTrkEndPos(t1,ep1); + Rotate(&pos2,orig,NormalizeAngle( angle-baseAngle )); + CreateEndAnchor(pos2,FALSE); + CreateEndAnchor(pos1,TRUE); + } + } + #ifdef DRAWCOUNT - InfoMessage( _(" Angle %0.3f #%ld"), angle, drawCount ); + InfoMessage( _("Angle %0.3f #%ld"), fabs(diff_angle), drawCount ); #else - InfoMessage( _(" Angle %0.3f"), angle ); + InfoMessage( _("Angle %0.3f %s"), fabs(diff_angle), clockwise?"Clockwise":"Counter-Clockwise" ); #endif wFlush(); drawEnable = TRUE; - } - MainRedraw(); - MapRedraw(); + } else + InfoMessage( _("Origin Set. Drag away to set start angle")); + return C_CONTINUE; + case C_UP: + DYNARR_RESET(trkSeg_t,anchors_da); state = 0; - if ( rotateAlignState == 1 ) { - if ( trk && GetTrkSelected(trk) ) { - InfoMessage( _("Click on the 2nd Unselected object") ); - rotateAlignState = 2; - } - return C_CONTINUE; - } - FreeTempStrings(); - if ( rotateAlignState == 2 ) { - //DrawMovedTracks(); - MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, orig, angle ); + if (t1 && ep1>=0 && t2 && ep2>=0) { + MoveToJoin(t2,ep2,t1,ep1); + CleanSegs(&tempSegs_da); rotateAlignState = 0; - } else if (drawnAngle) { - DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); - //DrawMovedTracks(); - MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, orig, angle ); + } else { + if ( rotateAlignState == 1 ) { + if ( trk && GetTrkSelected(trk) ) { + InfoMessage( _("Align: Click on the 2nd unselected object") ); + rotateAlignState = 2; + } + return C_CONTINUE; + } + CleanSegs(&tempSegs_da); + if ( rotateAlignState == 2 ) { + MoveTracks( FALSE, FALSE, TRUE, zero, orig, angle, TRUE ); + rotateAlignState = 0; + } else if (drawnAngle) { + MoveTracks( FALSE, FALSE, TRUE, zero, orig, NormalizeAngle( angle-baseAngle ), TRUE ); + } } - MainRedraw(); - MapRedraw(); + UndoEnd(); + tlist_da.cnt = 0; return C_TERMINATE; case C_CMDMENU: @@ -1501,16 +2143,65 @@ static STATUS_T CmdRotate( } } } + moveDescPos = pos; + moveDescTrk = trk; + SetUpMenu2(pos,trk); + menuPos = pos; wMenuPopupShow( selectPopup2M ); return C_CONTINUE; + case C_TEXT: + if ((action>>8) == 'd') { + panCenter = pos; + LOG( log_pan, 2, ( "PanCenter:Sel-%d %0.3f %0.3f\n", __LINE__, panCenter.x, panCenter.y ) ); + PanHere((void*)0); + } + if ((action>>8) == 'e') { + DoZoomExtents(0); + } + if ((action>>8) == '0' || (action>>8 == 'o')) { + PanMenuEnter('o'); + } + break; case C_REDRAW: + if (anchors_da.cnt) + DrawSegs( &tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack ); /* DO_REDRAW */ if ( state == 0 ) break; - if ( rotateAlignState != 2 ) - DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); - DrawSelectedTracksD( &mainD, wDrawColorWhite ); + if ( rotateAlignState != 2 ) { + DIST_T width = mainD.scale*0.5; + DrawLine( &tempD, base, orig, 0, wDrawColorBlue ); + if (drawnAngle) { + DrawLine( &tempD, orig_base, orig, (wDrawWidth)width, wDrawColorBlue ); + ANGLE_T a = DifferenceBetweenAngles(FindAngle(orig, orig_base),FindAngle(orig, base)); + + DIST_T dist = FindDistance(orig,base); + if (dist>(60.0/75.0)*mainD.scale) dist = (60.0/75.0)*mainD.scale; + + if (direction_set) { + if (clockwise) { + if (a<0) a = a + 360; + DrawArc( &tempD, orig, dist/2, FindAngle(orig,orig_base), a, FALSE, 0, wDrawColorBlue); + } else { + if (a>0) a = a - 360; + DrawArc( &tempD, orig, dist/2, FindAngle(orig,base), fabs(a), FALSE, 0, wDrawColorBlue); + } + DIST_T d; + d = mainD.scale*0.25; + ANGLE_T arrow_a = NormalizeAngle(FindAngle(orig,orig_base)+a/2); + coOrd arr1,arr2,arr3; + Translate(&arr2,orig,arrow_a,dist/2); + if (clockwise) arrow_a +=90; + else arrow_a -=90; + Translate(&arr1,arr2,arrow_a+135,d/2); + Translate(&arr3,arr2,arrow_a-135,d/2); + DrawLine( &tempD, arr1, arr2, 0, wDrawColorBlue ); + DrawLine( &tempD, arr2, arr3, 0, wDrawColorBlue ); + } + } + + } DrawMovedTracks(); break; @@ -1524,12 +2215,9 @@ static void QuickMove( void* pos) { 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 ); + MoveTracks( TRUE, TRUE, FALSE, move_pos, zero, 0.0, TRUE ); wDrawDelayUpdate( mainD.d, FALSE ); - MainRedraw(); - MapRedraw(); } static void QuickRotate( void* pangle ) @@ -1539,18 +2227,16 @@ static void QuickRotate( void* pangle ) return; wDrawDelayUpdate( mainD.d, TRUE ); GetMovedTracks(FALSE); - DrawSelectedTracksD( &mainD, wDrawColorWhite ); + //DrawSelectedTracksD( &mainD, wDrawColorWhite ); UndoStart( _("Rotate Tracks"), "Rotate Tracks" ); - MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, cmdMenuPos, angle ); + MoveTracks( TRUE, FALSE, TRUE, zero, cmdMenuPos, (double)angle/1000, TRUE); wDrawDelayUpdate( mainD.d, FALSE ); - MainRedraw(); - MapRedraw(); } static wMenu_p moveDescM; static wMenuToggle_p moveDescMI; -static track_p moveDescTrk; + static void ChangeDescFlag( wBool_t set, void * mode ) { wDrawDelayUpdate( mainD.d, TRUE ); @@ -1565,113 +2251,228 @@ static void ChangeDescFlag( wBool_t set, void * mode ) wDrawDelayUpdate( mainD.d, FALSE ); } -STATUS_T CmdMoveDescription( - wAction_t action, - coOrd pos ) -{ - static track_p trk; - static EPINX_T ep; - track_p trk1; - EPINX_T ep1; - DIST_T d, dd; - static int mode; - - switch (action) { - case C_START: - if ( labelWhen < 2 || mainD.scale > labelScale || - (labelEnable&(LABELENABLE_TRKDESC|LABELENABLE_LENGTHS|LABELENABLE_ENDPT_ELEV))==0 ) { - ErrorMessage( MSG_DESC_NOT_VISIBLE ); - return C_TERMINATE; - } - InfoMessage( _("Select and drag a description") ); - break; - case C_DOWN: - if ( labelWhen < 2 || mainD.scale > labelScale ) - return C_TERMINATE; - trk = NULL; - dd = 10000; - trk1 = NULL; +track_p FindTrackDescription(coOrd pos, EPINX_T * ep_o, int * mode_o, BOOL_T show_hidden, BOOL_T * hidden_o) { + track_p trk = NULL; + DIST_T d, dd = 10000; + track_p trk1 = NULL; + EPINX_T ep1=-1, ep=-1; + BOOL_T hidden_t, hidden; + coOrd dpos = pos; + coOrd cpos; + int mode = -1; while ( TrackIterate( &trk1 ) ) { if ( !GetLayerVisible(GetTrkLayer(trk1)) ) continue; if ( (!GetTrkVisible(trk1)) && drawTunnel==0 ) continue; - for ( ep1=0; ep1<GetTrkEndPtCnt(trk1); ep1++ ) { - d = EndPtDescriptionDistance( pos, trk1, ep1 ); - if ( d < dd ) { - dd = d; - trk = trk1; - ep = ep1; - mode = 0; + if ( (labelEnable&LABELENABLE_ENDPT_ELEV)!=0 && *mode_o <= 0) { + for ( ep1=0; ep1<GetTrkEndPtCnt(trk1); ep1++ ) { + d = EndPtDescriptionDistance( pos, trk1, ep1, &dpos, FALSE, NULL ); //No hidden + if ( d < dd ) { + dd = d; + trk = trk1; + ep = ep1; + mode = 0; + hidden = FALSE; + cpos= dpos; + } } } - if ( !QueryTrack( trk1, Q_HAS_DESC ) ) + if ( !QueryTrack( trk1, Q_HAS_DESC ) && (mode <0 || mode > 0) ) continue; - if ( ( GetTrkBits( trk1 ) & TB_HIDEDESC ) != 0 ) + if ((labelEnable&LABELENABLE_TRKDESC)==0) continue; - d = CompoundDescriptionDistance( pos, trk1 ); + if ( ( GetTrkBits( trk1 ) & TB_HIDEDESC ) != 0 ) { + if ( !show_hidden ) continue; + } + d = CompoundDescriptionDistance( pos, trk1, &dpos, show_hidden, &hidden_t ); if ( d < dd ) { dd = d; trk = trk1; ep = -1; mode = 1; + hidden = hidden_t; + cpos = dpos; } - d = CurveDescriptionDistance( pos, trk1 ); + d = CurveDescriptionDistance( pos, trk1, &dpos, show_hidden, &hidden_t ); if ( d < dd ) { dd = d; trk = trk1; ep = -1; mode = 2; + hidden = hidden_t; + cpos = dpos; } - d = CornuDescriptionDistance( pos, trk1 ); + d = CornuDescriptionDistance( pos, trk1, &dpos, show_hidden, &hidden_t ); if ( d < dd ) { dd = d; trk = trk1; ep = -1; mode = 3; + hidden = hidden_t; + cpos = dpos; } - d = BezierDescriptionDistance( pos, trk1 ); + d = BezierDescriptionDistance( pos, trk1, &dpos, show_hidden, &hidden_t ); if ( d < dd ) { dd = d; trk = trk1; ep = -1; mode = 4; + hidden = hidden_t; + cpos = dpos; } } - if (trk != NULL) { - UndoStart( _("Move Label"), "Modedesc( T%d )", GetTrkIndex(trk) ); - UndoModify( trk ); + if ((trk != NULL && (trk == OnTrack(&pos, FALSE, FALSE))) || + IsClose(d) || IsClose(FindDistance( pos, cpos) )) { //Only when close to a label or the track - not anywhere on layout! + if (ep_o) *ep_o = ep; + if (mode_o) *mode_o = mode; + if (hidden_o) *hidden_o = hidden; + return trk; + } + else return NULL; +} + +static long moveDescMode; + +STATUS_T CmdMoveDescription( + wAction_t action, + coOrd pos ) +{ + static track_p trk; + static EPINX_T ep; + static BOOL_T hidden; + static int mode; + BOOL_T bChanged; + + moveDescMode = (long)commandContext; //Context 0 = everything, 1 means elevations, 2 means descriptions + + bChanged = FALSE; + switch (action&0xFF) { + case C_START: + moveDescTrk = NULL; + moveDescPos = zero; + trk = NULL; + hidden = FALSE; + mode = -1; + if ( labelWhen < 2 || mainD.scale > labelScale || + (labelEnable&(LABELENABLE_TRKDESC|LABELENABLE_ENDPT_ELEV))==0 ) { + ErrorMessage( MSG_DESC_NOT_VISIBLE ); + return C_TERMINATE; + } + InfoMessage( _("Select and drag a description") ); + break; + case C_TEXT: + if (!moveDescTrk) return C_CONTINUE; + bChanged = FALSE; + if (action>>8 == 's') { + if ( ( GetTrkBits( moveDescTrk ) & TB_HIDEDESC) != 0 ) + bChanged = TRUE; + ClrTrkBits( moveDescTrk, TB_HIDEDESC ); + } else if (action>>8 == 'h') { + if ( ( GetTrkBits( moveDescTrk ) & TB_HIDEDESC) == 0 ) + bChanged = TRUE; + SetTrkBits( moveDescTrk, TB_HIDEDESC ); + } + if ( bChanged ) { + // We should push the draw/undraw of the description down + // but there is no clear way to do that + MainRedraw(); // CmdMoveDescription + } + /*no break*/ + case wActionMove: + if ( labelWhen < 2 || mainD.scale > labelScale ) return C_CONTINUE; + mode = moveDescMode-1; // -1 means everything, 0 means elevations only, 1 means descriptions only + if ((trk=FindTrackDescription(pos,&ep,&mode,TRUE,&hidden))!=NULL) { + if (mode==0) { + InfoMessage(_("Elevation description")); + } else { + if (hidden) { + InfoMessage(_("Hidden description - 's' to Show")); + moveDescTrk = trk; + moveDescPos = pos; + } else { + InfoMessage(_("Shown description - 'h' to Hide")); + moveDescTrk = trk; + moveDescPos = pos; + } + } + return C_CONTINUE; + } + InfoMessage( _("Select and drag a description") ); + break; + case C_DOWN: + if (( labelWhen < 2 || mainD.scale > labelScale ) || + (labelEnable&(LABELENABLE_TRKDESC|LABELENABLE_ENDPT_ELEV))==0 ) { + ErrorMessage( MSG_DESC_NOT_VISIBLE ); + return C_TERMINATE; + } + mode = moveDescMode-1; + trk = FindTrackDescription(pos,&ep,&mode,TRUE,&hidden); + if (trk == NULL ) + return C_CONTINUE; + if (hidden) { + ClrTrkBits( trk, TB_HIDEDESC ); + InfoMessage(_("Hidden Label - Drag to reveal")); + } else { + InfoMessage(_("Drag label")); } + UndoStart( _("Move Label"), "Modedesc( T%d )", GetTrkIndex(trk) ); + UndoModify( trk ); /* no break */ case C_MOVE: case C_UP: case C_REDRAW: if ( labelWhen < 2 || mainD.scale > labelScale ) return C_TERMINATE; - if (trk != NULL) { - switch (mode) { - case 0: - return EndPtDescriptionMove( trk, ep, action, pos ); - case 1: - 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 ); + if ( trk == NULL ) + return C_CONTINUE; + STATUS_T status = C_ERROR; + if ( action == C_REDRAW ) { + if (mode==0) { + DrawEndPt2( &tempD, trk, ep, wDrawColorBlue ); + } else { + if (hidden) { + DrawTrack( trk,&tempD,wDrawColorAqua); + } else { + DrawTrack( trk,&tempD,wDrawColorBlue); + } } } + switch (mode) { + case 0: + return EndPtDescriptionMove( trk, ep, action, pos ); + case 1: + 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 ); + } + hidden = FALSE; + if ( action == C_UP ) { + trk = NULL; + InfoMessage(_("To Hide, use Context Menu")); + } break; + case C_CMDMENU: - moveDescTrk = OnTrack( &pos, TRUE, FALSE ); + if (trk == NULL) { + moveDescTrk = OnTrack( &pos, TRUE, FALSE ); + moveDescPos = pos; + } else { + moveDescTrk = trk; + moveDescPos = pos; + } if ( moveDescTrk == NULL ) break; if ( ! QueryTrack( moveDescTrk, Q_HAS_DESC ) ) break; if ( moveDescM == NULL ) { moveDescM = MenuRegister( "Move Desc Toggle" ); - moveDescMI = wMenuToggleCreate( moveDescM, "", _("Show Description"), 0, TRUE, ChangeDescFlag, NULL ); + moveDescMI = wMenuToggleCreate( moveDescM, "", _("Show/Hide Description"), 0, TRUE, ChangeDescFlag, NULL ); } wMenuToggleSet( moveDescMI, ( GetTrkBits( moveDescTrk ) & TB_HIDEDESC ) == 0 ); + menuPos = pos; wMenuPopupShow( moveDescM ); break; @@ -1690,10 +2491,9 @@ static void FlipTracks( track_p trk, trk1; EPINX_T ep, ep1; - wSetCursor( wCursorWait ); + wSetCursor( mainD.d, wCursorWait ); /*UndoStart( "Move/Rotate Tracks", "move/rotate" );*/ if (selectedTrackCount <= incrementalDrawLimit) { - DrawMapBoundingBox( FALSE ); wDrawDelayUpdate( mainD.d, TRUE ); wDrawDelayUpdate( mapD.d, TRUE ); } @@ -1724,12 +2524,10 @@ static void FlipTracks( } else { wDrawDelayUpdate( mainD.d, FALSE ); wDrawDelayUpdate( mapD.d, FALSE ); - DrawMapBoundingBox( TRUE ); } - wSetCursor( wCursorNormal ); + wSetCursor( mainD.d, defaultCursor ); UndoEnd(); InfoCount( trackCount ); - MainRedraw(); } @@ -1759,25 +2557,15 @@ static STATUS_T CmdFlip( return C_TERMINATE; } pos0 = pos1 = pos; - DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); - MainRedraw(); - MapRedraw(); return C_CONTINUE; case C_MOVE: - DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); pos1 = pos; - 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 ); UndoStart( _("Flip Tracks"), "flip" ); FlipTracks( pos0, FindAngle( pos0, pos1 ) ); state = 0; - MainRedraw(); - MapRedraw(); return C_TERMINATE; #ifdef LATER @@ -1795,13 +2583,15 @@ static STATUS_T CmdFlip( return C_CONTINUE; } -static STATUS_T SelectArea( +static BOOL_T SelectArea( wAction_t action, coOrd pos ) { static coOrd pos0; static int state; static coOrd base, size, lo, hi; + static BOOL_T add; + static BOOL_T subtract; int cnt; track_p trk; @@ -1810,19 +2600,21 @@ static STATUS_T SelectArea( case C_START: state = 0; - return C_CONTINUE; + add = FALSE; + subtract = FALSE; + return FALSE; case C_DOWN: case C_RDOWN: pos0 = pos; - return C_CONTINUE; + add = (action == C_DOWN); + subtract = (action == C_RDOWN); + return TRUE; case C_MOVE: case C_RMOVE: if (state == 0) { state = 1; - } else { - DrawHilight( &mainD, base, size ); } base = pos0; size.x = pos.x - pos0.x; @@ -1835,24 +2627,24 @@ static STATUS_T SelectArea( size.y = - size.y; base.y = pos.y; } - DrawHilight( &mainD, base, size ); - return C_CONTINUE; + return TRUE; case C_UP: case C_RUP: if (state == 1) { state = 0; - DrawHilight( &mainD, base, size ); + add = (action == C_UP); + subtract = (action == C_RUP); cnt = 0; trk = NULL; + if (add && (selectMode == 0)) SetAllTrackSelect( FALSE ); //Remove all tracks first while ( TrackIterate( &trk ) ) { GetBoundingBox( trk, &hi, &lo ); if (GetLayerVisible( GetTrkLayer( trk ) ) && lo.x >= base.x && hi.x <= base.x+size.x && lo.y >= base.y && hi.y <= base.y+size.y) { - if ( (GetTrkSelected( trk )==0) == (action==C_UP) ) { - cnt++; - } + if ( (GetTrkSelected( trk )==0) == (action==C_UP) ) + cnt++; } } trk = NULL; @@ -1862,41 +2654,85 @@ static STATUS_T SelectArea( lo.x >= base.x && hi.x <= base.x+size.x && lo.y >= base.y && hi.y <= base.y+size.y) { if ( (GetTrkSelected( trk )==0) == (action==C_UP) ) { - if (cnt > incrementalDrawLimit) { + if (GetLayerModule(GetTrkLayer(trk))) { + if (add) + DoModuleTracks(GetTrkLayer(trk),SelectOneTrack,TRUE); + else + DoModuleTracks(GetTrkLayer(trk),SelectOneTrack,FALSE); + } else if (cnt > incrementalDrawLimit) { selectedTrackCount += (action==C_UP?1:-1); - if (action==C_UP) + if (add) SetTrkBits( trk, TB_SELECTED ); else ClrTrkBits( trk, TB_SELECTED ); } else { - SelectOneTrack( trk, action==C_UP ); + SelectOneTrack( trk, add ); } } } } + add = FALSE; + subtract = FALSE; + if (cnt > incrementalDrawLimit) { + MainRedraw(); // SelectArea C_UP + } else { + RedrawSelectedTracksBoundary(); + } SelectedTrackCountChange(); - if (cnt > incrementalDrawLimit) - MainRedraw(); } - return C_CONTINUE; + return FALSE; case C_CANCEL: - if (state == 1) { - DrawHilight( &mainD, base, size ); - state = 0; - } + state = 0; + add = FALSE; + subtract = FALSE; break; case C_REDRAW: if (state == 0) break; - DrawHilight( &mainD, base, size ); + //Draw to-be selected tracks versus not. + trk = NULL; + if (selectMode == 0 && add) HighlightSelectedTracks(NULL, TRUE, TRUE); + while ( TrackIterate( &trk ) ) { + GetBoundingBox( trk, &hi, &lo ); + if (GetLayerVisible( GetTrkLayer( trk ) ) && + lo.x >= base.x && hi.x <= base.x+size.x && + lo.y >= base.y && hi.y <= base.y+size.y) { + if (GetLayerModule(GetTrkLayer(trk))) { + if (add) + DoModuleTracks(GetTrkLayer(trk),DrawSingleTrack,TRUE); + else if (subtract) + DoModuleTracks(GetTrkLayer(trk),DrawSingleTrack,FALSE); + } else { + if (add) { + if (selectMode == 0 && add) + DrawTrack(trk,&tempD,wDrawColorPreviewSelected); + if (!GetTrkSelected(trk)) + DrawTrack(trk,&tempD,wDrawColorPreviewSelected); + } + else if (subtract) { + if (GetTrkSelected(trk)) + DrawTrack(trk,&tempD,wDrawColorPreviewUnselected); + } + } + } + } + if (add || subtract) { + DrawHilight( &tempD, base, size, add ); + return TRUE; + } break; } - return C_CONTINUE; + return FALSE; } +extern BOOL_T inDescribeCmd; +extern wIndex_t modifyCmdInx; +extern wIndex_t describeCmdInx; +extern wIndex_t panCmdInx; +extern wIndex_t trainCmdInx; static STATUS_T SelectTrack( coOrd pos ) @@ -1904,124 +2740,515 @@ static STATUS_T SelectTrack( track_p trk; char msg[STR_SIZE]; - if ((trk = OnTrack( &pos, TRUE, FALSE )) == NULL) { - return C_CONTINUE; + if (((trk = OnTrack( &pos, FALSE, FALSE )) == NULL) && selectZero) { //If option set and !ctrl or unset and ctrl + SetAllTrackSelect( FALSE ); //Unselect all + return C_CONTINUE; } + if (trk == NULL) return C_CONTINUE; + inDescribeCmd = FALSE; DescribeTrack( trk, msg, sizeof msg ); InfoMessage( msg ); - if (MyGetKeyState() & WKEY_SHIFT) { - SelectConnectedTracks( trk ); + if (GetLayerModule(GetTrkLayer(trk))) { + if (((MyGetKeyState() & WKEY_CTRL) && (selectMode==0)) || (!(MyGetKeyState() & WKEY_CTRL) && (selectMode==1)) ) { + DoModuleTracks(GetTrkLayer(trk),SelectOneTrack,!GetTrkSelected(trk)); + } else { + SetAllTrackSelect( FALSE ); //Just this Track if selectMode = 0 and !CTRL or selectMode = 1 and CTRL + DoModuleTracks(GetTrkLayer(trk),SelectOneTrack,TRUE); + } + RedrawSelectedTracksBoundary(); + return C_CONTINUE; + } + if (MyGetKeyState() & WKEY_SHIFT) { //All track up to + SelectConnectedTracks( trk, FALSE ); + } else if ((MyGetKeyState() & WKEY_CTRL) && (selectMode==0)) { + SelectOneTrack( trk, !GetTrkSelected(trk) ); + } else if (!(MyGetKeyState() & WKEY_CTRL) && (selectMode==1)) { + SelectOneTrack( trk, !GetTrkSelected(trk) ); } else { + SetAllTrackSelect( FALSE ); //Just this Track SelectOneTrack( trk, !GetTrkSelected(trk) ); } + RedrawSelectedTracksBoundary(); + return C_CONTINUE; } +static STATUS_T Activate( coOrd pos) { + track_p trk; + if ((trk = OnTrack( &pos, TRUE, FALSE )) == NULL) { + return C_CONTINUE; + } + if (GetLayerModule(GetTrkLayer(trk))) { + return C_CONTINUE; + } + if (QueryTrack(trk,Q_IS_ACTIVATEABLE)) ActivateTrack(trk); + + return C_CONTINUE; + +} + +track_p IsInsideABox(coOrd pos) { + track_p ts = NULL; + while ( TrackIterate( &ts ) ) { + if (!GetLayerVisible( GetTrkLayer( ts))) continue; + if (!GetTrkSelected(ts)) continue; + coOrd hi,lo; + GetBoundingBox(ts, &hi, &lo); + double boundary = mainD.scale*5/mainD.dpi; + if ((pos.x>=lo.x-boundary && pos.x<=hi.x+boundary) && (pos.y>=lo.y-boundary && pos.y<=hi.y+boundary)) { + return ts; + } + } + return NULL; +} + +void DrawHighlightBoxes(BOOL_T highlight_selected, BOOL_T select, track_p not_this) { + track_p ts = NULL; + coOrd origin,max; + BOOL_T first = TRUE; + while ( TrackIterate( &ts ) ) { + if ( !GetLayerVisible( GetTrkLayer( ts))) continue; + if (!GetTrkSelected(ts)) continue; + if (GetLayerModule(GetTrkLayer(ts))) { + DrawHighlightLayer(GetTrkLayer(ts)); + } + coOrd hi,lo; + if (highlight_selected && (ts != not_this)) DrawTrack(ts,&tempD,select?wDrawColorPreviewSelected:wDrawColorPreviewUnselected ); + GetBoundingBox(ts, &hi, &lo); + if (first) { + origin = lo; + max = hi; + first = FALSE; + } else { + if (lo.x <origin.x) origin.x = lo.x; + if (lo.y <origin.y) origin.y = lo.y; + if (hi.x >max.x) max.x = hi.x; + if (hi.y >max.y) max.y = hi.y; + } + } + if (!first) { + coOrd size; + size.x = max.x-origin.x; + size.y = max.y-origin.y; + wPos_t w,h; + w = (wPos_t)((size.x/mainD.scale)*mainD.dpi+0.5+10); + h = (wPos_t)((size.y/mainD.scale)*mainD.dpi+0.5+10); + wPos_t x, y; + tempD.CoOrd2Pix(&tempD,origin,&x,&y); + wDrawFilledRectangle(tempD.d, x-5, y-5, w, h, wDrawColorPowderedBlue, wDrawOptTemp|wDrawOptTransparent); + } + +} + +static STATUS_T CallModify(wAction_t action, + coOrd pos ) { + int rc = CmdModify(action,pos); + if (rc != C_CONTINUE) + doingDouble = FALSE; + return rc; +} + +static STATUS_T CallDescribe(wAction_t action, coOrd pos) { + int rc = CmdDescribe(action, pos); + return rc; +} + +static void CallPushDescribe(void * func) { + if (moveDescTrk) { + CallDescribe(C_START, moveDescPos); + CallDescribe(C_DOWN, moveDescPos); + CallDescribe(C_UP, moveDescPos); + } + return; +} + +static STATUS_T CmdSelect(wAction_t,coOrd); + +static void CallPushModify(void * func) { + if (moveDescTrk) { + CmdSelect(C_LDOUBLE, moveDescPos); + } + return; +} static STATUS_T CmdSelect( wAction_t action, coOrd pos ) { - static enum { AREA, MOVE, MOVEDESC, NONE } mode; - static BOOL_T doingMove = TRUE; - STATUS_T rc=C_CONTINUE; - if ( (action == C_DOWN || action == C_RDOWN) ) { - mode = AREA; - if (MyGetKeyState() & WKEY_SHIFT) { - mode = MOVE; - } else if (MyGetKeyState() & WKEY_CTRL) { - mode = MOVEDESC; + static BOOL_T doingMove; + static BOOL_T doingRotate; + + + + STATUS_T rc=C_CONTINUE; + static track_p trk = NULL; + typedef enum {NOSHOW,SHOWMOVE,SHOWROTATE,SHOWMODIFY,SHOWACTIVATE} showType; + static showType showMode; + + mode = AREA; + if (doingAlign || doingRotate || doingMove ) + mode = MOVE; + else { + if ( (action == C_DOWN) || (action == C_RDOWN) || ((action&0xFF) == wActionExtKey) ) { + mode = AREA; + if ( ((action&0xFF) == wActionExtKey) || ( //Moves don't need to be in a box + ( MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL|WKEY_ALT)) && IsInsideABox(pos)) ) //But cursors do + { + mode = MOVE; + } } } - switch (action) { + + switch (action&0xFF) { case C_START: - InfoMessage( _("Select tracks") ); -#ifdef LATER - if ((!importMove) && selectedTrackCount > 0) { - SetAllTrackSelect( FALSE ); - } -#endif - importMove = FALSE; + InfoMessage( _("Select track") ); + doingMove = FALSE; + doingRotate = FALSE; + doingAlign = FALSE; + doingDouble = FALSE; + showMode = NOSHOW; SelectArea( action, pos ); wMenuPushEnable( rotateAlignMI, FALSE ); + wSetCursor(mainD.d,defaultCursor); + mode = AREA; + trk = NULL; + break; + + case wActionModKey: + case wActionMove: + if (doingDouble) { + return CallModify(action,pos); + } + showMode = NOSHOW; + DYNARR_RESET(trkSeg_t,anchors_da); + coOrd p = pos; + trk = OnTrack( &p, FALSE, FALSE ); + track_p ht; + if ((selectedTrackCount==0) && (trk == NULL)) return C_CONTINUE; + if (trk && !CheckTrackLayerSilent( trk ) ) { + if (GetLayerFrozen(GetTrkLayer(trk)) ) { + trk = NULL; + InfoMessage(_("Track is in Frozen Layer")); + return C_CONTINUE; + } + } + if (selectedTrackCount>0) { + if ((ht = IsInsideABox(pos)) != NULL) { + if ((MyGetKeyState()&WKEY_SHIFT)) { + CreateMoveAnchor(pos); + showMode = SHOWMOVE; + } else if ((MyGetKeyState()&WKEY_CTRL)) { + CreateRotateAnchor(pos); + showMode = SHOWROTATE; + } else if (!GetLayerModule(GetTrkLayer(ht))) { + if (QueryTrack( ht, Q_CAN_MODIFY_CONTROL_POINTS ) || + QueryTrack( ht, Q_IS_CORNU ) || + (QueryTrack( ht, Q_IS_DRAW ) && !QueryTrack( ht, Q_IS_TEXT))) { + CreateModifyAnchor(pos); + showMode = SHOWMODIFY; + } else { + if (QueryTrack(ht,Q_IS_ACTIVATEABLE)) + CreateActivateAnchor(pos); + showMode = SHOWACTIVATE; + } + } + } + } break; case C_DOWN: - case C_UP: - case C_MOVE: case C_RDOWN: - case C_RUP: - case C_RMOVE: - case C_REDRAW: + if (doingDouble) { + return CallModify(action,pos); + } + DYNARR_RESET(trkSeg_t,anchors_da); switch (mode) { + rc = C_CONTINUE; case MOVE: - if (SelectedTracksAreFrozen()) { + if (SelectedTracksAreFrozen() || (selectedTrackCount==0)) { rc = C_TERMINATE; - mode = NONE; - } else if (action >= C_DOWN && action <= C_UP) { - rc = CmdMove( action, pos ); - doingMove = TRUE; - } else if (action >= C_RDOWN && action <= C_RUP) { - rc = CmdRotate( action-C_RDOWN+C_DOWN, pos ); doingMove = FALSE; - } else if (action == C_REDRAW) { - if (doingMove) { - rc = CmdMove( C_REDRAW, pos ); - } else { - rc = CmdRotate( C_REDRAW, pos ); - } + } else if ((MyGetKeyState()&(WKEY_CTRL|WKEY_SHIFT))==WKEY_CTRL) { + doingRotate = TRUE; + doingMove = FALSE; + RotateAlign( FALSE ); + rc = CmdRotate( action, pos ); + } else if ((MyGetKeyState()&(WKEY_SHIFT|WKEY_CTRL))==WKEY_SHIFT) { + doingMove = TRUE; + doingRotate = FALSE; + rc = CmdMove( action, pos ); } break; - case MOVEDESC: - rc = CmdMoveDescription( action, pos ); + case AREA: + doingMove = FALSE; + doingRotate = FALSE; + SelectArea( action, pos ); + break; + default: ; + } + trk = NULL; + return rc; + break; + case wActionExtKey: + case C_RMOVE: + case C_MOVE: + if (doingDouble) { + return CallModify(action,pos); + } + if ((action&0xFF) == wActionExtKey && ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL)) == (WKEY_SHIFT|WKEY_CTRL))) { //Both + arrow + doingMove = TRUE; + mode = MOVE; + } + DYNARR_RESET(trkSeg_t,anchors_da); + switch (mode) { + case MOVE: + if (SelectedTracksAreFrozen() || (selectedTrackCount==0)) { + rc = C_TERMINATE; + tlist_da.cnt = 0; + doingMove = FALSE; + doingRotate = FALSE; + } else if (doingRotate == TRUE) { + RotateAlign( FALSE ); + rc = CmdRotate( action, pos ); + } else if (doingMove == TRUE) { + rc = CmdMove( action, pos ); + } break; case AREA: - rc = SelectArea( action, pos ); + doingMove = FALSE; + doingRotate = FALSE; + SelectArea( action, pos ); + break; + default: ; + } + if ((action&0xFF) == wActionExtKey && ((MyGetKeyState() & (WKEY_SHIFT|WKEY_CTRL)) == (WKEY_SHIFT|WKEY_CTRL))) //Both + doingMove = FALSE; + return rc; + break; + case C_RUP: + case C_UP: + if (doingDouble) { + return CallModify(action,pos); + } + DYNARR_RESET(trkSeg_t,anchors_da); + switch (mode) { + case MOVE: + if (SelectedTracksAreFrozen() || (selectedTrackCount==0)) { + rc = C_TERMINATE; + doingMove = FALSE; + doingRotate = FALSE; + } else if (doingRotate == TRUE) { + RotateAlign( FALSE ); + rc = CmdRotate( action, pos ); + } else if (doingMove == TRUE) { + rc = CmdMove( action, pos ); + } break; - case NONE: + case AREA: + doingMove = FALSE; + doingRotate = FALSE; + SelectArea( action, pos ); + rc = C_CONTINUE; break; + default: ; } - if (action == C_UP || action == C_RUP) - mode = AREA; + doingMove = FALSE; + doingRotate = FALSE; + mode = AREA; return rc; - - case wActionMove: break; + case C_REDRAW: + if (doingDouble) { + return CallModify(action,pos); + } + if (doingMove) { + rc = CmdMove( C_REDRAW, pos ); + } else if (doingRotate) { + rc = CmdRotate( C_REDRAW, pos ); + } + + //Once doing a move or a rotate, make an early exit + if (doingMove || doingRotate) { + if (anchors_da.cnt) { + DrawSegs( &tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack ); + } + return C_CONTINUE; + } + BOOL_T AreaSelect = FALSE; + // Draw the selected area, no-op if none selected + if (mode==AREA) { + AreaSelect = SelectArea( action, pos ); + if (AreaSelect) return C_CONTINUE; + } + + // Highlight a whole Module's worth of tracks if we are hovering over one + if (trk && GetLayerModule(GetTrkLayer(trk))) { + if ( (selectMode == 1) && ((MyGetKeyState() & (WKEY_CTRL|WKEY_SHIFT)) != WKEY_CTRL) ) + DoModuleTracks(GetTrkLayer(trk),DrawSingleTrack,!GetTrkSelected(trk)); //Toggle + else + DoModuleTracks(GetTrkLayer(trk),DrawSingleTrack,TRUE); + DrawHighlightLayer(GetTrkLayer(trk)); + } + + //Draw all existing highlight boxes only + DrawHighlightBoxes(FALSE, FALSE, trk); + + // If not on a track, show all tracks as going to be de-selected if selectZero on + if (!trk && selectZero ) { + HighlightSelectedTracks(NULL, TRUE, TRUE); + //Handle the SHIFT+ which means SelectAllConnected case + } else if ( trk && !IsTrackDeleted(trk)) { + if ((MyGetKeyState() & WKEY_SHIFT) ) + SelectConnectedTracks(trk, TRUE); //Highlight all connected + //Normal case - handle track we are hovering over + else { + //Select=Add + if (selectMode == 1) { + if ((MyGetKeyState() & (WKEY_CTRL|WKEY_SHIFT)) == WKEY_CTRL) { + //Only Highlight if adding + if (!GetTrkSelected(trk)) + DrawTrack(trk,&tempD,wDrawColorPreviewSelected); + } else { + if (GetTrkSelected(trk)) + DrawTrack(trk,&tempD,wDrawColorPreviewUnselected); //Toggle + else + DrawTrack(trk,&tempD,wDrawColorPreviewSelected); + } + //Select=Only + } else { + if ((MyGetKeyState() & (WKEY_CTRL|WKEY_SHIFT)) == WKEY_CTRL) { + if (GetTrkSelected(trk)) + DrawTrack(trk,&tempD,wDrawColorPreviewUnselected); //Toggle + else + DrawTrack(trk,&tempD,wDrawColorPreviewSelected); + } else { + //Only Highlight if adding + if (!GetTrkSelected(trk)) + DrawTrack(trk,&tempD,wDrawColorPreviewSelected ); + } + } + } + // Now Highlight the rest of the tracks or Module + if (GetLayerModule(GetTrkLayer(trk))) { + if (selectMode == 1 && ((MyGetKeyState() & (WKEY_CTRL|WKEY_SHIFT)) != WKEY_CTRL) ) + DoModuleTracks(GetTrkLayer(trk),DrawSingleTrack,!GetTrkSelected(trk)); //Toggle + else + DoModuleTracks(GetTrkLayer(trk),DrawSingleTrack,TRUE); + DrawHighlightLayer(GetTrkLayer(trk)); + } else { + //Select=Add + if (selectMode == 1) { + if (((MyGetKeyState() & (WKEY_CTRL|WKEY_SHIFT)) == WKEY_CTRL)) + HighlightSelectedTracks(trk, TRUE, TRUE); + //else + // HighlightSelectedTracks(trk, TRUE, FALSE); Highlight all selected + //Select=Only + } else { + if (((MyGetKeyState() & (WKEY_CTRL|WKEY_SHIFT)) != WKEY_CTRL)) + HighlightSelectedTracks(trk, TRUE, TRUE); + //else + // HighlightSelectedTracks(trk, TRUE, TRUE); Highlight all selected + } + } + } + //Finally add the anchors for any actions or snaps + if (anchors_da.cnt) { + DrawSegs( &tempD, zero, 0.0, &anchors(0), anchors_da.cnt, trackGauge, wDrawColorBlack ); + } + + return rc; + case C_LCLICK: + if (doingDouble) { + return CallModify(action,pos); + } switch (mode) { case MOVE: - case MOVEDESC: - break; case AREA: - case NONE: - return SelectTrack( pos ); + if (doingAlign) { + rc = CmdRotate (C_DOWN, pos); + rc = CmdRotate (C_UP, pos); + } else + rc = SelectTrack( pos ); + doingRotate = FALSE; + doingMove = FALSE; + return rc; } mode = AREA; break; + case C_LDOUBLE: + if (doingDouble) { + return C_CONTINUE; + } + switch (mode) { + case AREA: + if ((ht = OnTrack(&pos,FALSE,FALSE))!=NULL) { + if (QueryTrack( ht, Q_CAN_MODIFY_CONTROL_POINTS ) || + QueryTrack( ht, Q_IS_CORNU ) || + (QueryTrack( ht, Q_IS_DRAW ) && !QueryTrack( ht, Q_IS_TEXT ))) { + doingDouble = TRUE; + CallModify(C_START,pos); + if (doingDouble == FALSE) return C_CONTINUE; + CallModify(C_LDOUBLE,pos); + } else if (QueryTrack( ht, Q_IS_ACTIVATEABLE)){ + return Activate(pos); + } + } + break; + case MOVE: + default: + break; + } + break; + case C_CMDMENU: + if (doingDouble) { + return CallModify(action,pos); + } + menuPos = pos; 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; - } - } - } + SetUpMenu2(pos,trk); wMenuPopupShow( selectPopup2M ); } return C_CONTINUE; + case C_TEXT: + if (doingDouble) { + return CallModify(action,pos); + } + if ((action>>8) == 'c') { + panCenter = pos; + LOG( log_pan, 2, ( "PanCenter:Sel-%d %0.3f %0.3f\n", __LINE__, panCenter.x, panCenter.y ) ); + PanHere((void*)0); + } + if ((action>>8) == 'e') { + DoZoomExtents(0); + } + if ((action>>8) == '0' || (action>>8 == 'o')) { + PanMenuEnter('o'); + } + if ((action>>8) == '?') { + if((moveDescTrk = OnTrack(&pos,FALSE,FALSE)) != NULL) + moveDescPos = pos; + CallPushDescribe((void*)0); + wSetCursor(mainD.d,defaultCursor); + moveDescTrk = NULL; + } + break; + case C_FINISH: + if (doingMove) UndoEnd(); + doingDouble = FALSE; + break; + default: + if (doingDouble) return CallModify(action, pos); } + return C_CONTINUE; } @@ -2029,6 +3256,7 @@ static STATUS_T CmdSelect( #include "bitmaps/select.xpm" #include "bitmaps/delete.xpm" #include "bitmaps/tunnel.xpm" +#include "bitmaps/bridge.xpm" #include "bitmaps/move.xpm" #include "bitmaps/rotate.xpm" #include "bitmaps/flip.xpm" @@ -2044,11 +3272,27 @@ static void SetMoveMode( char * line ) enableMoveDraw = ((tmp&0x10) == 0); } +static void moveDescription( void ) { + if (!moveDescTrk) return; + int hidden = GetTrkBits( moveDescTrk) &TB_HIDEDESC ; + if (hidden) + ClrTrkBits( moveDescTrk, TB_HIDEDESC ); + else + SetTrkBits( moveDescTrk, TB_HIDEDESC ); +} + EXPORT void InitCmdSelect( wMenu_p menu ) { selectCmdInx = AddMenuButton( menu, CmdSelect, "cmdSelect", _("Select"), wIconCreatePixMap(select_xpm), - LEVEL0, IC_CANCEL|IC_POPUP|IC_LCLICK|IC_CMDMENU, ACCL_SELECT, NULL ); + LEVEL0, IC_CANCEL|IC_POPUP|IC_LCLICK|IC_CMDMENU|IC_WANT_MOVE|IC_WANT_MODKEYS, ACCL_SELECT, NULL ); +} + +extern wIndex_t trainCmdInx; + +EXPORT void InitCmdSelect2( wMenu_p menu ) { + + endpt_bm = wDrawBitMapCreate( mainD.d, bmendpt_width, bmendpt_width, 7, 7, bmendpt_bits ); angle_bm[0] = wDrawBitMapCreate( mainD.d, bma90_width, bma90_width, 7, 7, bma90_bits ); angle_bm[1] = wDrawBitMapCreate( mainD.d, bma135_width, bma135_width, 7, 7, bma135_bits ); @@ -2058,24 +3302,76 @@ EXPORT void InitCmdSelect( wMenu_p menu ) wPrefGetInteger( "draw", "movemode", &moveMode, MAXMOVEMODE ); if (moveMode > MAXMOVEMODE || moveMode < 0) moveMode = MAXMOVEMODE; - - selectPopup1M = MenuRegister( "Move Draw Mode" ); - quickMove1M[0] = wMenuToggleCreate( selectPopup1M, "", _("Normal"), 0, quickMove==0, ChangeQuickMove, (void *) 0 ); - quickMove1M[1] = wMenuToggleCreate( selectPopup1M, "", _("Simple"), 0, quickMove==1, ChangeQuickMove, (void *) 1 ); - quickMove1M[2] = wMenuToggleCreate( selectPopup1M, "", _("End Points"), 0, quickMove==2, ChangeQuickMove, (void *) 2 ); - selectPopup2M = MenuRegister( "Move Draw Mode " ); - quickMove2M[0] = wMenuToggleCreate( selectPopup2M, "", _("Normal"), 0, quickMove==0, ChangeQuickMove, (void *) 0 ); - quickMove2M[1] = wMenuToggleCreate( selectPopup2M, "", _("Simple"), 0, quickMove==1, ChangeQuickMove, (void *) 1 ); - quickMove2M[2] = wMenuToggleCreate( selectPopup2M, "", _("End Points"), 0, quickMove==2, ChangeQuickMove, (void *) 2 ); + selectPopup1M = MenuRegister( "Select Mode Menu" ); + wMenuPushCreate(selectPopup1M, "", _("Undo"), 0,(wMenuCallBack_p) UndoUndo, (void *) 0); + wMenuPushCreate(selectPopup1M, "", _("Redo"), 0,(wMenuCallBack_p) UndoRedo, (void *) 0); + wMenuSeparatorCreate( selectPopup1M ); + wMenuPushCreate(selectPopup1M, "cmdDescribeMode", GetBalloonHelpStr("cmdModifyMode"), 0, DoCommandB, (void*) (intptr_t) modifyCmdInx); + wMenuPushCreate(selectPopup1M, "cmdPanMode", GetBalloonHelpStr("cmdPanMode"), 0, DoCommandB, (void*) (intptr_t) panCmdInx); + wMenuPushCreate(selectPopup1M, "cmdTrainMode", GetBalloonHelpStr("cmdTrainMode"), 0, DoCommandB, (void*) (intptr_t) trainCmdInx); + wMenuSeparatorCreate( selectPopup1M ); + wMenuPushCreate(selectPopup1M, "", _("Zoom In"), 0,(wMenuCallBack_p) DoZoomUp, (void*) 1); + wMenuPushCreate( selectPopup1M, "", _("Zoom to extents - 'e'"), 0, (wMenuCallBack_p)DoZoomExtents, (void*) 0); + wMenu_p zoomPop1 = wMenuMenuCreate(selectPopup1M, "", _("&Zoom")); + InitCmdZoom(NULL, NULL, zoomPop1, NULL); + wMenuPushCreate(selectPopup1M, "", _("Zoom Out"), 0, (wMenuCallBack_p) DoZoomDown, (void*) 1); + wMenuPushCreate(selectPopup1M, "", _("Pan to Origin - 'o'/'0'"), 0, (wMenuCallBack_p) PanMenuEnter, (void*) 'o'); + wMenuPushCreate(selectPopup1M, "", _("Pan Center Here - 'c'"), 0, (wMenuCallBack_p) PanHere, (void*) 3); + wMenuSeparatorCreate( selectPopup1M ); + wMenuPushCreate(selectPopup1M, "", _("Select All"), 0,(wMenuCallBack_p) SetAllTrackSelect, (void *) 1); + wMenuPushCreate(selectPopup1M, "",_("Select Current Layer"), 0,(wMenuCallBack_p) SelectCurrentLayer, (void *) 0); + wMenuSeparatorCreate( selectPopup1M ); + + selectPopup2M = MenuRegister( "Track Selected Menu " ); + wMenuPushCreate(selectPopup2M, "", _("Undo"), 0,(wMenuCallBack_p) UndoUndo, (void *) 0); + wMenuPushCreate(selectPopup2M, "", _("Redo"), 0,(wMenuCallBack_p) UndoRedo, (void *) 0); + wMenuSeparatorCreate( selectPopup2M ); + wMenuPushCreate(selectPopup2M, "", _("Zoom In"), 0,(wMenuCallBack_p) DoZoomUp, (void*) 1); + wMenuPushCreate(selectPopup2M, "", _("Zoom Out"), 0, (wMenuCallBack_p) DoZoomDown, (void*) 1); + wMenuPushCreate(selectPopup2M, "", _("Pan Center Here - 'c'"), 0, (wMenuCallBack_p) PanHere, (void*) 3); wMenuSeparatorCreate( selectPopup2M ); + wMenuPushCreate(selectPopup2M, "", _("Deselect All"), 0, (wMenuCallBack_p) SetAllTrackSelect, (void *) 0); + wMenuSeparatorCreate( selectPopup2M ); + wMenuPushCreate(selectPopup2M, "", _("Properties -'?'"), 0,(wMenuCallBack_p) CallPushDescribe, (void*)0); + menuPushModify = wMenuPushCreate(selectPopup2M, "", _("Modify/Activate Track"), 0,(wMenuCallBack_p) CallPushModify, (void*)0); + wMenuSeparatorCreate( selectPopup2M ); + wMenuPushCreate(selectPopup2M, "", _("Cut"), 0,(wMenuCallBack_p) EditCut, (void *) 0); + wMenuPushCreate(selectPopup2M, "", _("Copy"), 0,(wMenuCallBack_p) EditCopy, (void *) 0); + wMenuPushCreate(selectPopup2M, "", _("Paste"), 0, (wMenuCallBack_p) EditPaste, (void *) 0); + wMenuPushCreate(selectPopup2M, "", _("Clone"), 0, (wMenuCallBack_p) EditClone, (void *) 0); AddMoveMenu( selectPopup2M, QuickMove); + selectPopup2RM = wMenuMenuCreate(selectPopup2M, "", _("Rotate...")); + AddRotateMenu( selectPopup2RM, QuickRotate ); + rotateAlignMI = wMenuPushCreate( selectPopup2RM, "", _("Align"), 0, (wMenuCallBack_p)RotateAlign, (void* ) 1 ); + wMenuSeparatorCreate( selectPopup2M ); + descriptionMI = wMenuPushCreate(selectPopup2M, "cmdMoveLabel", _("Show/Hide Description"), 0, (wMenuCallBack_p)moveDescription, (void*) 0); + wMenuSeparatorCreate( selectPopup2M ); + hideMI = wMenuPushCreate(selectPopup2M, "", _("Hide/NoHide"), 0,(wMenuCallBack_p) SelectTunnel, (void *) 0); + bridgeMI = wMenuPushCreate(selectPopup2M, "", _("Bridge/NoBridge"), 0,(wMenuCallBack_p) SelectBridge, (void *) 0); + tiesMI = wMenuPushCreate(selectPopup2M, "", _("NoTies/Ties"), 0,(wMenuCallBack_p) SelectTies, (void *) 0); + selectPopup2TM = wMenuMenuCreate(selectPopup2M, "", _("Thickness...")); + wMenuPushCreate( selectPopup2TM, "", _("Thin Tracks"), 0, (void*)(wMenuCallBack_p)SelectTrackWidth, (void *)0 ); + wMenuPushCreate( selectPopup2TM, "", _("Medium Tracks"), 0, (void*)(wMenuCallBack_p)SelectTrackWidth, (void *)2 ); + wMenuPushCreate( selectPopup2TM, "", _("Thick Tracks"), 0, (void*)(wMenuCallBack_p)SelectTrackWidth, (void *)3 ); + selectPopup2TYM = wMenuMenuCreate( selectPopup2M, "", _("LineType...") ); + wMenuPushCreate( selectPopup2TYM, "", _("Solid Line"), 0, (wMenuCallBack_p)SelectLineType, (void*)0 ); + wMenuPushCreate( selectPopup2TYM, "", _("Dashed Line"), 0, (wMenuCallBack_p)SelectLineType, (void*)1 ); + wMenuPushCreate( selectPopup2TYM, "", _("Dotted Line"), 0, (wMenuCallBack_p)SelectLineType, (void*)2 ); + wMenuPushCreate( selectPopup2TYM, "", _("Dash-Dotted Line"), 0, (wMenuCallBack_p)SelectLineType, (void*)3 ); + wMenuPushCreate( selectPopup2TYM, "", _("Dash-Dot-Dotted Line"), 0, (wMenuCallBack_p)SelectLineType, (void*)4 ); + wMenuSeparatorCreate( selectPopup2M ); + wMenuPushCreate(selectPopup2M, "", _("Move To Front"), 0,(wMenuCallBack_p) SelectAbove,(void *) 0); + wMenuPushCreate(selectPopup2M, "", _("Move To Back"), 0,(wMenuCallBack_p) SelectBelow, (void *) 0); wMenuSeparatorCreate( selectPopup2M ); - AddRotateMenu( selectPopup2M, QuickRotate ); - rotateAlignMI = wMenuPushCreate( selectPopup2M, "", _("Align"), 0, (wMenuCallBack_p)RotateAlign, NULL ); + wMenuPushCreate(selectPopup2M, "", _("Group"), 0,(wMenuCallBack_p) DoGroup, (void *) 0); + wMenuPushCreate(selectPopup2M, "", _("UnGroup"), 0,(wMenuCallBack_p) DoUngroup, (void *) 0); + wMenuSeparatorCreate( selectPopup2M ); + ParamRegister( &rescalePG ); } + EXPORT void InitCmdDelete( void ) { wIcon_p icon; @@ -2091,27 +3387,29 @@ EXPORT void InitCmdTunnel( void ) wIcon_p icon; icon = wIconCreatePixMap( tunnel_xpm ); AddToolbarButton( "cmdTunnel", icon, IC_SELECTED|IC_POPUP, (addButtonCallBack_t)SelectTunnel, NULL ); -#ifdef LATER - tunnelCmdInx = AddButton( "cmdTunnel", _("Tunnel"), - (addButtonCallBack_t)SelectTunnel, NULL, IC_SELECTED|IC_POPUP, NULL, LEVEL0_50, ACCL_TUNNEL, - (wControl_p)wButtonCreate(mainW, 0, 0, "cmdTunnel", (char*)bm_p, BO_ICON, 0, (wButtonCallBack_p)SelectTunnel, 0 ) ); -#endif +} + +EXPORT void InitCmdBridge( void) +{ + wIcon_p icon; + icon = wIconCreatePixMap( bridge_xpm ); + AddToolbarButton( "cmdBridge", icon, IC_SELECTED|IC_POPUP, (addButtonCallBack_t)SelectBridge, NULL ); } EXPORT void InitCmdMoveDescription( wMenu_p menu ) { AddMenuButton( menu, CmdMoveDescription, "cmdMoveLabel", _("Move Description"), wIconCreatePixMap(movedesc_xpm), - LEVEL0, IC_STICKY|IC_POPUP|IC_CMDMENU, ACCL_MOVEDESC, NULL ); + LEVEL0, IC_STICKY|IC_POPUP3|IC_CMDMENU|IC_WANT_MOVE, ACCL_MOVEDESC, (void*) 0 ); } EXPORT void InitCmdMove( wMenu_p menu ) { moveCmdInx = AddMenuButton( menu, CmdMove, "cmdMove", _("Move"), wIconCreatePixMap(move_xpm), - LEVEL0, IC_STICKY|IC_SELECTED|IC_CMDMENU, ACCL_MOVE, NULL ); + LEVEL0, IC_STICKY|IC_SELECTED|IC_CMDMENU|IC_WANT_MOVE, ACCL_MOVE, NULL ); rotateCmdInx = AddMenuButton( menu, CmdRotate, "cmdRotate", _("Rotate"), wIconCreatePixMap(rotate_xpm), - LEVEL0, IC_STICKY|IC_SELECTED|IC_CMDMENU, ACCL_ROTATE, NULL ); + LEVEL0, IC_STICKY|IC_SELECTED|IC_CMDMENU|IC_WANT_MOVE, ACCL_ROTATE, NULL ); /*flipCmdInx =*/ AddMenuButton( menu, CmdFlip, "cmdFlip", _("Flip"), wIconCreatePixMap(flip_xpm), LEVEL0, IC_STICKY|IC_SELECTED|IC_CMDMENU, ACCL_FLIP, NULL ); } |