diff options
Diffstat (limited to 'app/bin/cselect.c')
-rw-r--r-- | app/bin/cselect.c | 1918 |
1 files changed, 1918 insertions, 0 deletions
diff --git a/app/bin/cselect.c b/app/bin/cselect.c new file mode 100644 index 0000000..1bafd45 --- /dev/null +++ b/app/bin/cselect.c @@ -0,0 +1,1918 @@ +/** \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 + * Copyright (C) 2005 Dave Bullis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include "track.h" +/*#include "trackx.h"*/ +#include "ccurve.h" +#define PRIVATE_EXTRADATA +#include "compound.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" + +EXPORT wIndex_t selectCmdInx; +EXPORT wIndex_t moveCmdInx; +EXPORT wIndex_t rotateCmdInx; + +#define MAXMOVEMODE (3) +static long moveMode = MAXMOVEMODE; +static BOOL_T enableMoveDraw = TRUE; +static BOOL_T move0B; +struct extraData { char junk[2000]; }; + +static wDrawBitMap_p endpt_bm; +static wDrawBitMap_p angle_bm[4]; + + long quickMove = 0; + BOOL_T importMove = 0; + int incrementalDrawLimit = 20; + +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 );\ + Tlist(tlist_da.cnt-1) = T; } +static track_p *tlist2 = NULL; + +static wMenu_p selectPopup1M; +static wMenu_p selectPopup2M; + +static void DrawSelectedTracksD( drawCmd_p d, wDrawColor color ); + +/***************************************************************************** + * + * SELECT TRACKS + * + */ + +EXPORT long selectedTrackCount = 0; /**< number of currently selected track components */ + +static void SelectedTrackCountChange( void ) +{ + static long oldCount = 0; + if (selectedTrackCount != oldCount) { + if (oldCount == 0) { + /* going non-0 */ + EnableCommands(); + } else if (selectedTrackCount == 0) { + /* going 0 */ + EnableCommands(); + } + oldCount = selectedTrackCount; + } +} + + +static void DrawTrackAndEndPts( + track_p trk, + wDrawColor color ) +{ + EPINX_T ep, ep2; + track_p trk2; + + DrawTrack( trk, &mainD, color ); + for (ep=0;ep<GetTrkEndPtCnt(trk);ep++) { + if ((trk2=GetTrkEndTrk(trk,ep)) != NULL) { + ASSERT( !IsTrackDeleted(trk) ); + ep2 = GetEndPtConnectedToMe( trk2, trk ); + DrawEndPt( &mainD, trk2, ep2, + (color==wDrawColorBlack && GetTrkSelected(trk2))? + selectedColor:color ); + } + } +} + + +EXPORT void SetAllTrackSelect( BOOL_T select ) +{ + track_p trk; + BOOL_T doRedraw = FALSE; + + if (select || selectedTrackCount > incrementalDrawLimit) { + doRedraw = TRUE; + } else { + wDrawDelayUpdate( mainD.d, TRUE ); + } + selectedTrackCount = 0; + trk = NULL; + while ( TrackIterate( &trk ) ) { + if ((!select) || GetLayerVisible( GetTrkLayer( trk ))) { + 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) + DrawTrackAndEndPts( trk, wDrawColorBlack ); + } + } + } + SelectedTrackCountChange(); + if (doRedraw) { + MainRedraw(); + } else { + wDrawDelayUpdate( mainD.d, FALSE ); + } +} + +/* Invert selected state of all visible objects. + * + * \param none + * \return none + */ + +EXPORT void InvertTrackSelect( void *ptr ) +{ + track_p trk; + + trk = NULL; + while ( TrackIterate( &trk ) ) { + if (GetLayerVisible( GetTrkLayer( trk ))) { + if (GetTrkSelected(trk)) + { + ClrTrkBits( trk, TB_SELECTED ); + selectedTrackCount--; + } + else + SetTrkBits( trk, TB_SELECTED ); + selectedTrackCount++; + } + } + + SelectedTrackCountChange(); + MainRedraw(); +} + +/* Select orphaned (ie single) track pieces. + * + * \param none + * \return none + */ + +EXPORT void OrphanedTrackSelect( void *ptr ) +{ + track_p trk; + EPINX_T ep; + int cnt ; + + trk = NULL; + + while( TrackIterate( &trk ) ) { + cnt = 0; + if( GetLayerVisible( GetTrkLayer( trk ))) { + for( ep = 0; ep < GetTrkEndPtCnt( trk ); ep++ ) { + if( GetTrkEndTrk( trk, ep ) ) + cnt++; + } + + if( !cnt && GetTrkEndPtCnt( trk )) { + SetTrkBits( trk, TB_SELECTED ); + DrawTrackAndEndPts( trk, wDrawColorBlack ); + selectedTrackCount++; + } + } + } + SelectedTrackCountChange(); + MainRedraw(); +} + + +static void SelectOneTrack( + track_p trk, + wBool_t selected ) +{ + DrawTrackAndEndPts( trk, wDrawColorWhite ); + if (selected) { + SetTrkBits( trk, TB_SELECTED ); + selectedTrackCount++; + } else { + ClrTrkBits( trk, TB_SELECTED ); + selectedTrackCount--; + } + SelectedTrackCountChange(); + DrawTrackAndEndPts( trk, wDrawColorBlack ); +} + + +static void SelectConnectedTracks( + track_p trk ) +{ + track_p trk1; + int inx; + EPINX_T ep; + tlist_da.cnt = 0; + TlistAppend( trk ); + InfoCount( 0 ); + wDrawDelayUpdate( mainD.d, FALSE ); + for (inx=0; inx<tlist_da.cnt; inx++) { + if ( inx > 0 && selectedTrackCount == 0 ) + return; + trk = Tlist(inx); + if (inx!=0 && + GetTrkSelected(trk)) + continue; + for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { + trk1 = GetTrkEndTrk( trk, ep ); + if (trk1 && (!GetTrkSelected(trk1)) && GetLayerVisible( GetTrkLayer( trk1 )) ) { + TlistAppend( trk1 ) + } + } + if (!GetTrkSelected(trk)) { + SelectOneTrack( trk, TRUE ); + InfoCount( inx+1 ); + } + SetTrkBits(trk, TB_SELECTED); + } + wDrawDelayUpdate( mainD.d, TRUE ); + wFlush(); + InfoCount( trackCount ); +} + + + +typedef BOOL_T (*doSelectedTrackCallBack_t)(track_p, BOOL_T); +static void DoSelectedTracks( doSelectedTrackCallBack_t doit ) +{ + track_p trk; + trk = NULL; + while ( TrackIterate( &trk ) ) { + if (GetTrkSelected(trk)) { + if ( !doit( trk, TRUE ) ) { + break; + } + } + } +} + + +static BOOL_T SelectedTracksAreFrozen( void ) +{ + track_p trk; + trk = NULL; + while ( TrackIterate( &trk ) ) { + if ( GetTrkSelected(trk) ) { + if ( GetLayerFrozen( GetTrkLayer( trk ) ) ) { + ErrorMessage( MSG_SEL_TRK_FROZEN ); + return TRUE; + } + } + } + return FALSE; +} + + +EXPORT void SelectTrackWidth( void* width ) +{ + track_p trk; + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount<=0) { + ErrorMessage( MSG_NO_SELECTED_TRK ); + return; + } + UndoStart( _("Change Track Width"), "trackwidth" ); + trk = NULL; + wDrawDelayUpdate( mainD.d, TRUE ); + while ( TrackIterate( &trk ) ) { + if (GetTrkSelected(trk)) { + DrawTrackAndEndPts( trk, wDrawColorWhite ); + UndoModify( trk ); + SetTrkWidth( trk, (int)(long)width ); + DrawTrackAndEndPts( trk, wDrawColorBlack ); + } + } + wDrawDelayUpdate( mainD.d, FALSE ); + UndoEnd(); +} + + +EXPORT void SelectDelete( void ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + UndoStart( _("Delete Tracks"), "delete" ); + wDrawDelayUpdate( mainD.d, TRUE ); + wDrawDelayUpdate( mapD.d, TRUE ); + DoSelectedTracks( DeleteTrack ); + wDrawDelayUpdate( mainD.d, FALSE ); + wDrawDelayUpdate( mapD.d, FALSE ); + selectedTrackCount = 0; + SelectedTrackCountChange(); + UndoEnd(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } +} + + +BOOL_T flipHiddenDoSelectRecount; +static BOOL_T FlipHidden( track_p trk, BOOL_T junk ) +{ + EPINX_T i; + track_p trk2; + + DrawTrackAndEndPts( trk, wDrawColorWhite ); + /*UndrawNewTrack( trk ); + for (i=0; i<GetTrkEndPtCnt(trk); i++) + if ((trk2=GetTrkEndTrk(trk,i)) != NULL) { + UndrawNewTrack( trk2 ); + }*/ + UndoModify( trk ); + if ( drawTunnel == 0 ) + flipHiddenDoSelectRecount = TRUE; + if (GetTrkVisible(trk)) { + ClrTrkBits( trk, TB_VISIBLE|(drawTunnel==0?TB_SELECTED:0) ); + } else { + SetTrkBits( trk, TB_VISIBLE ); + } + /*DrawNewTrack( trk );*/ + DrawTrackAndEndPts( trk, wDrawColorBlack ); + for (i=0; i<GetTrkEndPtCnt(trk); i++) + if ((trk2=GetTrkEndTrk(trk,i)) != NULL) { + UndoModify( trk2 ); + /*DrawNewTrack( trk2 );*/ + } + return TRUE; +} + + +EXPORT void SelectTunnel( void ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + flipHiddenDoSelectRecount = FALSE; + UndoStart( _("Hide Tracks (Tunnel)"), "tunnel" ); + wDrawDelayUpdate( mainD.d, TRUE ); + DoSelectedTracks( FlipHidden ); + wDrawDelayUpdate( mainD.d, FALSE ); + UndoEnd(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } + if ( flipHiddenDoSelectRecount ) + SelectRecount(); +} + + +EXPORT void SelectRecount( void ) +{ + track_p trk; + selectedTrackCount = 0; + trk = NULL; + while ( TrackIterate( &trk ) ) { + if (GetTrkSelected(trk)) { + selectedTrackCount++; + } + } + SelectedTrackCountChange(); +} + + +static BOOL_T SetLayer( track_p trk, BOOL_T junk ) +{ + UndoModify( trk ); + SetTrkLayer( trk, curLayer ); + return TRUE; +} + +EXPORT void MoveSelectedTracksToCurrentLayer( void ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + UndoStart( _("Move To Current Layer"), "changeLayer" ); + DoSelectedTracks( SetLayer ); + UndoEnd(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } +} + +EXPORT void SelectCurrentLayer( void ) +{ + track_p trk; + trk = NULL; + while ( TrackIterate( &trk ) ) { + if ((!GetTrkSelected(trk)) && GetTrkLayer(trk) == curLayer ) { + SelectOneTrack( trk, TRUE ); + } + } +} + + +static BOOL_T ClearElevation( track_p trk, BOOL_T junk ) +{ + EPINX_T ep; + for ( ep=0; ep<GetTrkEndPtCnt(trk); ep++ ) { + if (!EndPtIsIgnoredElev(trk,ep)) { + DrawEndPt2( &mainD, trk, ep, wDrawColorWhite ); + SetTrkEndElev( trk, ep, ELEV_NONE, 0.0, NULL ); + ClrTrkElev( trk ); + DrawEndPt2( &mainD, trk, ep, wDrawColorBlack ); + } + } + return TRUE; +} + +EXPORT void ClearElevations( void ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + UndoStart( _("Clear Elevations"), "clear elevations" ); + DoSelectedTracks( ClearElevation ); + UpdateAllElevations(); + UndoEnd(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } +} + + +static DIST_T elevDelta; +static BOOL_T AddElevation( track_p trk, BOOL_T junk ) +{ + track_p trk1; + EPINX_T ep, ep1; + int mode; + DIST_T elev; + + for ( ep=0; ep<GetTrkEndPtCnt(trk); ep++ ) { + if ((trk1=GetTrkEndTrk(trk,ep))) { + ep1 = GetEndPtConnectedToMe( trk1, trk ); + if (ep1 >= 0) { + if (GetTrkSelected(trk1) && GetTrkIndex(trk1)<GetTrkIndex(trk)) + continue; + } + } + if (EndPtIsDefinedElev(trk,ep)) { + DrawEndPt2( &mainD, trk, ep, wDrawColorWhite ); + mode = GetTrkEndElevUnmaskedMode(trk,ep); + elev = GetTrkEndElevHeight(trk,ep); + SetTrkEndElev( trk, ep, mode, elev+elevDelta, NULL ); + ClrTrkElev( trk ); + DrawEndPt2( &mainD, trk, ep, wDrawColorBlack ); + } + } + return TRUE; +} + +EXPORT void AddElevations( DIST_T delta ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + elevDelta = delta; + UndoStart( _("Add Elevations"), "add elevations" ); + DoSelectedTracks( AddElevation ); + UndoEnd(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } + UpdateAllElevations(); +} + + +EXPORT void DoRefreshCompound( void ) +{ + if (SelectedTracksAreFrozen()) + return; + if (selectedTrackCount>0) { + UndoStart( _("Refresh Compound"), "refresh compound" ); + DoSelectedTracks( RefreshCompound ); + RefreshCompound( NULL, FALSE ); + UndoEnd(); + MainRedraw(); + } else { + ErrorMessage( MSG_NO_SELECTED_TRK ); + } +} + + +static drawCmd_t tempSegsD = { + NULL, &tempSegDrawFuncs, DC_GROUP, 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 ) ) + continue; + ClrTrkBits( trk, TB_SELECTED ); + DrawTrack( trk, &tempSegsD, wDrawColorBlack ); + SetTrkBits( trk, TB_SELECTED ); + } + } + tempSegDrawFuncs.options = oldOptions; +} + +static char rescaleFromScale[20]; +static char rescaleFromGauge[20]; + +static char * rescaleToggleLabels[] = { N_("Scale"), N_("Ratio"), NULL }; +static long rescaleMode; +static wIndex_t rescaleFromScaleInx; +static wIndex_t rescaleFromGaugeInx; +static wIndex_t rescaleToScaleInx; +static wIndex_t rescaleToGaugeInx; +static wIndex_t rescaleToInx; +static long rescaleNoChangeDim = FALSE; +static FLOAT_T rescalePercent; +static char * rescaleChangeDimLabels[] = { N_("Do not resize track"), NULL }; +static paramFloatRange_t r0o001_10000 = { 0.001, 10000.0 }; +static paramData_t rescalePLs[] = { +#define I_RESCALE_MODE (0) + { PD_RADIO, &rescaleMode, "toggle", PDO_NOPREF, &rescaleToggleLabels, N_("Rescale by:"), BC_HORZ|BC_NOBORDER }, +#define I_RESCALE_FROM_SCALE (1) + { PD_STRING, rescaleFromScale, "fromS", PDO_NOPREF, (void *)100, N_("From:") }, +#define I_RESCALE_FROM_GAUGE (2) + { PD_STRING, rescaleFromGauge, "fromG", PDO_NOPREF|PDO_DLGHORZ, (void *)100, " / " }, +#define I_RESCALE_TO_SCALE (3) + { PD_DROPLIST, &rescaleToScaleInx, "toS", PDO_NOPREF|PDO_LISTINDEX, (void *)100, N_("To: ") }, +#define I_RESCALE_TO_GAUGE (4) + { PD_DROPLIST, &rescaleToGaugeInx, "toG", PDO_NOPREF|PDO_LISTINDEX|PDO_DLGHORZ, NULL, " / " }, +#define I_RESCALE_CHANGE (5) + { PD_TOGGLE, &rescaleNoChangeDim, "change-dim", 0, &rescaleChangeDimLabels, "", BC_HORZ|BC_NOBORDER }, +#define I_RESCALE_PERCENT (6) + { PD_FLOAT, &rescalePercent, "ratio", 0, &r0o001_10000, N_("Ratio") }, + { PD_MESSAGE, "%", NULL, PDO_DLGHORZ } }; +static paramGroup_t rescalePG = { "rescale", 0, rescalePLs, sizeof rescalePLs/sizeof rescalePLs[0] }; + + +static long getboundsCount; +static coOrd getboundsLo, getboundsHi; + +static BOOL_T GetboundsDoIt( track_p trk, BOOL_T junk ) +{ + coOrd hi, lo; + + GetBoundingBox( trk, &hi, &lo ); + if ( getboundsCount == 0 ) { + getboundsLo = lo; + getboundsHi = hi; + } else { + if ( lo.x < getboundsLo.x ) getboundsLo.x = lo.x; + if ( lo.y < getboundsLo.y ) getboundsLo.y = lo.y; + if ( hi.x > getboundsHi.x ) getboundsHi.x = hi.x; + if ( hi.y > getboundsHi.y ) getboundsHi.y = hi.y; + } + getboundsCount++; + return TRUE; +} + +static coOrd rescaleShift; +static BOOL_T RescaleDoIt( track_p trk, BOOL_T junk ) +{ + EPINX_T ep, ep1; + track_p trk1; + UndoModify(trk); + if ( rescalePercent != 100.0 ) { + for (ep=0; ep<GetTrkEndPtCnt(trk); ep++) { + if ((trk1 = GetTrkEndTrk(trk,ep)) != NULL && + !GetTrkSelected(trk1)) { + ep1 = GetEndPtConnectedToMe( trk1, trk ); + DisconnectTracks( trk, ep, trk1, ep1 ); + } + } + /* should the track dimensions ie. length or radius be changed as well? */ + if( rescaleNoChangeDim == 0 ) + RescaleTrack( trk, rescalePercent/100.0, rescaleShift ); + } + + if ( rescaleMode==0 ) + SetTrkScale( trk, rescaleToInx ); + getboundsCount++; + return TRUE; +} + + +static void RescaleDlgOk( + void * junk ) +{ + coOrd center, size; + DIST_T d; + FLOAT_T ratio = rescalePercent/100.0; + + UndoStart( _("Rescale Tracks"), "Rescale" ); + getboundsCount = 0; + DoSelectedTracks( GetboundsDoIt ); + center.x = (getboundsLo.x+getboundsHi.x)/2.0; + center.y = (getboundsLo.y+getboundsHi.y)/2.0; + size.x = (getboundsHi.x-getboundsLo.x)/2.0*ratio; + size.y = (getboundsHi.y-getboundsLo.y)/2.0*ratio; + getboundsLo.x = center.x - size.x; + getboundsLo.y = center.y - size.y; + getboundsHi.x = center.x + size.x; + getboundsHi.y = center.y + size.y; + if ( getboundsLo.x < 0 ) { + getboundsHi.x -= getboundsLo.x; + getboundsLo.x = 0; + } else if ( getboundsHi.x > mapD.size.x ) { + d = getboundsHi.x - mapD.size.x; + if ( getboundsLo.x < d ) + d = getboundsLo.x; + getboundsHi.x -= d; + getboundsLo.x -= d; + } + if ( getboundsLo.y < 0 ) { + getboundsHi.y -= getboundsLo.y; + getboundsLo.y = 0; + } else if ( getboundsHi.y > mapD.size.y ) { + d = getboundsHi.y - mapD.size.y; + if ( getboundsLo.y < d ) + d = getboundsLo.y; + getboundsHi.y -= d; + getboundsLo.y -= d; + } + if ( rescaleNoChangeDim == 0 && + (getboundsHi.x > mapD.size.x || + getboundsHi.y > mapD.size.y )) { + NoticeMessage( MSG_RESCALE_TOO_BIG, _("Ok"), NULL, FormatDistance(getboundsHi.x), FormatDistance(getboundsHi.y) ); + } + rescaleShift.x = (getboundsLo.x+getboundsHi.x)/2.0 - center.x*ratio; + rescaleShift.y = (getboundsLo.y+getboundsHi.y)/2.0 - center.y*ratio; + + rescaleToInx = GetScaleInx( rescaleToScaleInx, rescaleToGaugeInx ); + DoSelectedTracks( RescaleDoIt ); + DoRedraw(); + wHide( rescalePG.win ); +} + + +static void RescaleDlgUpdate( + paramGroup_p pg, + int inx, + void * valueP ) +{ + switch (inx) { + case I_RESCALE_MODE: + wControlShow( pg->paramPtr[I_RESCALE_FROM_SCALE].control, rescaleMode==0 ); + wControlActive( pg->paramPtr[I_RESCALE_FROM_SCALE].control, FALSE ); + wControlShow( pg->paramPtr[I_RESCALE_TO_SCALE].control, rescaleMode==0 ); + wControlShow( pg->paramPtr[I_RESCALE_FROM_GAUGE].control, rescaleMode==0 ); + wControlActive( pg->paramPtr[I_RESCALE_FROM_GAUGE].control, FALSE ); + wControlShow( pg->paramPtr[I_RESCALE_TO_GAUGE].control, rescaleMode==0 ); + wControlShow( pg->paramPtr[I_RESCALE_CHANGE].control, rescaleMode==0 ); + wControlActive( pg->paramPtr[I_RESCALE_PERCENT].control, rescaleMode==1 ); + if ( rescaleMode!=0 ) + break; + case I_RESCALE_TO_SCALE: + LoadGaugeList( (wList_p)rescalePLs[I_RESCALE_TO_GAUGE].control, *((int *)valueP) ); + rescaleToGaugeInx = 0; + ParamLoadControl( pg, I_RESCALE_TO_GAUGE ); + ParamLoadControl( pg, I_RESCALE_TO_SCALE ); + rescalePercent = GetScaleDescRatio(rescaleFromScaleInx)/GetScaleDescRatio(rescaleToScaleInx)*100.0; + wControlActive( pg->paramPtr[I_RESCALE_CHANGE].control, (rescaleFromScaleInx != rescaleToScaleInx) ); + ParamLoadControl( pg, I_RESCALE_PERCENT ); + break; + case I_RESCALE_TO_GAUGE: + ParamLoadControl( pg, I_RESCALE_TO_GAUGE ); + break; + case I_RESCALE_FROM_SCALE: + ParamLoadControl( pg, I_RESCALE_FROM_SCALE ); + break; + case I_RESCALE_FROM_GAUGE: + ParamLoadControl( pg, I_RESCALE_FROM_GAUGE ); + break; + case I_RESCALE_CHANGE: + ParamLoadControl( pg, I_RESCALE_CHANGE ); + break; + case -1: + break; + } + ParamDialogOkActive( pg, rescalePercent!=100.0 || rescaleFromGaugeInx != rescaleToGaugeInx ); +} + +/** + * Get the scale gauge information for the selected track pieces. + * FIXME: special cases like tracks pieces with different gauges or scale need to be handled + * + * \param IN trk track element + * \param IN junk + * \return TRUE; + */ + +static BOOL_T SelectedScaleGauge( track_p trk, BOOL_T junk ) +{ + char *scaleName; + SCALEINX_T scale; + SCALEDESCINX_T scaleInx; + GAUGEINX_T gaugeInx; + + scale = GetTrkScale( trk ); + scaleName = GetScaleName( scale ); + if( strcmp( scaleName, "*" )) { + GetScaleGauge( scale, &scaleInx, &gaugeInx ); + strcpy( rescaleFromScale,GetScaleDesc( scaleInx )); + strcpy( rescaleFromGauge, GetGaugeDesc( scaleInx, gaugeInx )); + + rescaleFromScaleInx = scaleInx; + rescaleFromGaugeInx = gaugeInx; + rescaleToScaleInx = scaleInx; + rescaleToGaugeInx = gaugeInx; + } + + return TRUE; +} + +/** + * Bring up the rescale dialog. The dialog for rescaling the selected pieces + * of track is created if necessary and shown. Handling of user input is done via + * RescaleDlgUpdate() + */ + +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; + rescalePercent = 100.0; + } + + DoSelectedTracks( SelectedScaleGauge ); + + RescaleDlgUpdate( &rescalePG, I_RESCALE_MODE, &rescaleMode ); + RescaleDlgUpdate( &rescalePG, I_RESCALE_CHANGE, &rescaleMode ); + + RescaleDlgUpdate( &rescalePG, I_RESCALE_FROM_GAUGE, rescaleFromGauge ); + RescaleDlgUpdate( &rescalePG, I_RESCALE_FROM_SCALE, rescaleFromScale ); + + RescaleDlgUpdate( &rescalePG, I_RESCALE_TO_SCALE, &rescaleToScaleInx ); + RescaleDlgUpdate( &rescalePG, I_RESCALE_TO_GAUGE, &rescaleToGaugeInx ); + + 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 ) +{ + wIndex_t inx; + track_p trk; + coOrd lo, hi; + /*wDrawDelayUpdate( d->d, TRUE );*/ + for (inx=0; inx<tlist_da.cnt; inx++) { + trk = Tlist(inx); + if (d != &mapD) { + GetBoundingBox( trk, &hi, &lo ); + if ( OFF_D( d->orig, d->size, lo, hi ) ) + continue; + } + DrawTrack( trk, d, color ); + } + /*wDrawDelayUpdate( d->d, FALSE );*/ +} + +static BOOL_T AddSelectedTrack( + track_p trk, BOOL_T junk ) +{ + DYNARR_APPEND( track_p, tlist_da, 10 ); + DYNARR_LAST( track_p, tlist_da ) = trk; + return TRUE; +} + +static coOrd moveOrig; +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 }; + + + + +/* Draw selected (on-screen) tracks to tempSegs, + and use drawSegs to draw them (moved/rotated) to mainD + Incremently add new tracks as they scroll on-screen. +*/ + + +static int movedCnt; +static void AccumulateTracks( void ) +{ + wIndex_t inx; + track_p trk; + 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++; + } + } + } + moveD.options &= ~DC_QUICK; + InfoCount( movedCnt ); + /*wDrawDelayUpdate( moveD.d, FALSE );*/ +} + + +static void GetMovedTracks( BOOL_T undraw ) +{ + wSetCursor( 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; + 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 ); + 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 );*/ + } +} + +static void SetMoveD( BOOL_T moveB, coOrd orig, ANGLE_T angle ) +{ + int inx; + + moveOrig.x = orig.x; + moveOrig.y = orig.y; + moveAngle = angle; + if (!moveB) { + Rotate( &orig, zero, angle ); + moveOrig.x -= orig.x; + moveOrig.y -= orig.y; + } + if (moveB) { + moveD_lo.x = mainD.orig.x - orig.x; + moveD_lo.y = mainD.orig.y - orig.y; + moveD_hi = moveD_lo; + moveD_hi.x += mainD.size.x; + moveD_hi.y += mainD.size.y; + } else { + coOrd corner[3]; + corner[2].x = mainD.orig.x; + corner[0].x = corner[1].x = mainD.orig.x + mainD.size.x; + corner[0].y = mainD.orig.y; + corner[1].y = corner[2].y = mainD.orig.y + mainD.size.y; + moveD_hi = mainD.orig; + Rotate( &moveD_hi, orig, -angle ); + moveD_lo = moveD_hi; + for (inx=0;inx<3;inx++) { + Rotate( &corner[inx], orig, -angle ); + if (corner[inx].x < moveD_lo.x) + moveD_lo.x = corner[inx].x; + if (corner[inx].y < moveD_lo.y) + moveD_lo.y = corner[inx].y; + if (corner[inx].x > moveD_hi.x) + moveD_hi.x = corner[inx].x; + if (corner[inx].y > moveD_hi.y) + moveD_hi.y = corner[inx].y; + } + } + AccumulateTracks(); +} + + +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; + } + 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 ( !OFF_MAIND( pos, pos ) ) + DrawBitMap( &tempD, pos, bm, selectedColor ); + } + } +} + + + +static void MoveTracks( + BOOL_T eraseFirst, + BOOL_T move, + BOOL_T rotate, + coOrd base, + coOrd orig, + ANGLE_T angle ) +{ + track_p trk, trk1; + EPINX_T ep, ep1; + int inx; + + wSetCursor( wCursorWait ); + /*UndoStart( "Move/Rotate Tracks", "move/rotate" );*/ + if (tlist_da.cnt <= incrementalDrawLimit) { + DrawMapBoundingBox( FALSE ); + if (eraseFirst) + DrawSelectedTracksD( &mainD, 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 ); + 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; + InfoCount( trackCount ); +} + + +void MoveToJoin( + track_p trk0, + EPINX_T ep0, + track_p trk1, + EPINX_T ep1 ) +{ + coOrd orig; + coOrd base; + ANGLE_T angle; + + UndoStart( _("Move To Join"), "Move To Join" ); + base = GetTrkEndPos(trk0,ep0); + orig = GetTrkEndPos(trk1, ep1 ); + base.x = orig.x - base.x; + base.y = orig.y - base.y; + angle = GetTrkEndAngle(trk1,ep1); + angle -= GetTrkEndAngle(trk0,ep0); + angle += 180.0; + angle = NormalizeAngle( angle ); + GetMovedTracks( FALSE ); + MoveTracks( TRUE, TRUE, TRUE, base, orig, angle ); + UndrawNewTrack( trk0 ); + UndrawNewTrack( trk1 ); + ConnectTracks( trk0, ep0, trk1, ep1 ); + DrawNewTrack( trk0 ); + DrawNewTrack( trk1 ); +} + +static STATUS_T CmdMove( + wAction_t action, + coOrd pos ) +{ + static coOrd base; + static coOrd orig; + static int state; + + switch( action ) { + + case C_START: + if (selectedTrackCount == 0) { + ErrorMessage( MSG_NO_SELECTED_TRK ); + return C_TERMINATE; + } + if (SelectedTracksAreFrozen()) { + return C_TERMINATE; + } + InfoMessage( _("Drag to move selected tracks") ); + state = 0; + break; + case C_DOWN: + if (SelectedTracksAreFrozen()) { + return C_TERMINATE; + } + UndoStart( _("Move Tracks"), "move" ); + base = zero; + orig = pos; + GetMovedTracks(quickMove != MOVE_QUICK); + SetMoveD( TRUE, base, 0.0 ); + DrawMovedTracks(); + drawCount = 0; + state = 1; + MainRedraw(); + return C_CONTINUE; + case C_MOVE: + drawEnable = enableMoveDraw; + DrawMovedTracks(); + base.x = pos.x - orig.x; + base.y = pos.y - orig.y; + SnapPos( &base ); + SetMoveD( TRUE, base, 0.0 ); + DrawMovedTracks(); +#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(); + return C_CONTINUE; + case C_UP: + state = 0; + DrawMovedTracks(); + MoveTracks( quickMove==MOVE_QUICK, TRUE, FALSE, base, zero, 0.0 ); + return C_TERMINATE; + + case C_CMDMENU: + wMenuPopupShow( selectPopup1M ); + return C_CONTINUE; + + case C_REDRAW: + /* DO_REDRAW */ + if ( state == 0 ) + break; + DrawSelectedTracksD( &mainD, wDrawColorWhite ); + DrawMovedTracks(); + break; + + default: + break; + } + return C_CONTINUE; +} + + +wMenuPush_p rotateAlignMI; +int rotateAlignState = 0; + +static void RotateAlign( void ) +{ + rotateAlignState = 1; + InfoMessage( _("Click on selected object to align") ); +} + +static STATUS_T CmdRotate( + wAction_t action, + coOrd pos ) +{ + static coOrd base; + static coOrd orig; + static ANGLE_T angle; + static BOOL_T drawnAngle; + static ANGLE_T baseAngle; + static track_p trk; + ANGLE_T angle1; + coOrd pos1; + static int state; + + switch( action ) { + + case C_START: + state = 0; + if (selectedTrackCount == 0) { + ErrorMessage( MSG_NO_SELECTED_TRK ); + return C_TERMINATE; + } + if (SelectedTracksAreFrozen()) { + return C_TERMINATE; + } + InfoMessage( _("Drag to rotate selected tracks") ); + wMenuPushEnable( rotateAlignMI, TRUE ); + rotateAlignState = 0; + break; + case C_DOWN: + state = 1; + if (SelectedTracksAreFrozen()) { + return C_TERMINATE; + } + UndoStart( _("Rotate Tracks"), "rotate" ); + if ( rotateAlignState == 0 ) { + drawnAngle = FALSE; + angle = 0; + base = orig = pos; + GetMovedTracks(FALSE); + /*DrawLine( &mainD, base, orig, 0, wDrawColorBlack ); + DrawMovedTracks(FALSE, orig, angle);*/ + } else { + pos1 = pos; + onTrackInSplit = TRUE; + trk = OnTrack( &pos, TRUE, FALSE ); + onTrackInSplit = FALSE; + if ( trk == NULL ) return C_CONTINUE; + angle1 = NormalizeAngle( GetAngleAtPoint( trk, pos, NULL, NULL ) ); + if ( rotateAlignState == 1 ) { + if ( !GetTrkSelected(trk) ) { + NoticeMessage( MSG_1ST_TRACK_MUST_BE_SELECTED, _("Ok"), NULL ); + } else { + base = pos; + baseAngle = angle1; + getboundsCount = 0; + DoSelectedTracks( GetboundsDoIt ); + orig.x = (getboundsLo.x+getboundsHi.x)/2.0; + orig.y = (getboundsLo.y+getboundsHi.y)/2.0; +/*printf( "orig = [%0.3f %0.3f], baseAngle = %0.3f\n", orig.x, orig.y, baseAngle );*/ + } + } else { + if ( GetTrkSelected(trk) ) { + ErrorMessage( MSG_2ND_TRACK_MUST_BE_UNSELECTED ); + 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 ); +/*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(); + } + } + MainRedraw(); + return C_CONTINUE; + case C_MOVE: + if ( rotateAlignState == 1 ) + return C_CONTINUE; + if ( rotateAlignState == 2 ) { + pos1 = pos; + onTrackInSplit = TRUE; + trk = OnTrack( &pos, TRUE, FALSE ); + onTrackInSplit = FALSE; + if ( trk == NULL ) + return C_CONTINUE; + if ( GetTrkSelected(trk) ) { + 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 ) + angle = NormalizeAngle( angle + 180.0 ); + if ( NormalizeAngle( FindAngle( pos, pos1 ) - angle1 ) < 180.0 ) + angle = NormalizeAngle( angle + 180.0 ); + if ( angle1 > 180.0 ) angle1 -= 180.0; + InfoMessage( _("Angle %0.3f"), angle1 ); + SetMoveD( FALSE, orig, angle ); +/*printf( "angle 2 = %0.3f\n", angle );*/ + DrawMovedTracks(); + MainRedraw(); + 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 = FindAngle( orig, pos ); + if (!drawnAngle) { + baseAngle = angle; + drawnAngle = 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) ); + } + DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); + SetMoveD( FALSE, orig, angle ); + DrawMovedTracks(); +#ifdef DRAWCOUNT + InfoMessage( _(" Angle %0.3f #%ld"), angle, drawCount ); +#else + InfoMessage( _(" Angle %0.3f"), angle ); +#endif + wFlush(); + drawEnable = TRUE; + } + MainRedraw(); + return C_CONTINUE; + case C_UP: + state = 0; + if ( rotateAlignState == 1 ) { + if ( trk && GetTrkSelected(trk) ) { + InfoMessage( _("Click on the 2nd Unselected object") ); + rotateAlignState = 2; + } + return C_CONTINUE; + } + if ( rotateAlignState == 2 ) { + DrawMovedTracks(); + MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, orig, angle ); + rotateAlignState = 0; + } else if (drawnAngle) { + DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); + DrawMovedTracks(); + MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, orig, angle ); + } + MainRedraw(); + return C_TERMINATE; + + case C_CMDMENU: + wMenuPopupShow( selectPopup2M ); + return C_CONTINUE; + + case C_REDRAW: + /* DO_REDRAW */ + if ( state == 0 ) + break; + if ( rotateAlignState != 2 ) + DrawLine( &tempD, base, orig, 0, wDrawColorBlack ); + DrawSelectedTracksD( &mainD, wDrawColorWhite ); + DrawMovedTracks(); + break; + + } + return C_CONTINUE; +} + +static void QuickRotate( void* pangle ) +{ + ANGLE_T angle = (ANGLE_T)(long)pangle; + if ( SelectedTracksAreFrozen() ) + return; + wDrawDelayUpdate( mainD.d, TRUE ); + GetMovedTracks(FALSE); + DrawSelectedTracksD( &mainD, wDrawColorWhite ); + UndoStart( _("Rotate Tracks"), "Rotate Tracks" ); + MoveTracks( quickMove==MOVE_QUICK, FALSE, TRUE, zero, cmdMenuPos, angle ); + wDrawDelayUpdate( mainD.d, FALSE ); +} + + +static wMenu_p moveDescM; +static wMenuToggle_p moveDescMI; +static track_p moveDescTrk; +static void ChangeDescFlag( wBool_t set, void * mode ) +{ + wDrawDelayUpdate( mainD.d, TRUE ); + UndoStart( _("Toggle Label"), "Modedesc( T%d )", GetTrkIndex(moveDescTrk) ); + UndoModify( moveDescTrk ); + UndrawNewTrack( moveDescTrk ); + if ( ( GetTrkBits( moveDescTrk ) & TB_HIDEDESC ) == 0 ) + SetTrkBits( moveDescTrk, TB_HIDEDESC ); + else + ClrTrkBits( moveDescTrk, TB_HIDEDESC ); + DrawNewTrack( moveDescTrk ); + 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; + 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 ( !QueryTrack( trk1, Q_HAS_DESC ) ) + continue; + if ( ( GetTrkBits( trk1 ) & TB_HIDEDESC ) != 0 ) + continue; + d = CompoundDescriptionDistance( pos, trk1 ); + if ( d < dd ) { + dd = d; + trk = trk1; + ep = -1; + mode = 1; + } + d = CurveDescriptionDistance( pos, trk1 ); + if ( d < dd ) { + dd = d; + trk = trk1; + ep = -1; + mode = 2; + } + } + if (trk != NULL) { + UndoStart( _("Move Label"), "Modedesc( T%d )", GetTrkIndex(trk) ); + UndoModify( trk ); + } + 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 C_CMDMENU: + moveDescTrk = OnTrack( &pos, TRUE, FALSE ); + 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 ); + } + wMenuToggleSet( moveDescMI, ( GetTrkBits( moveDescTrk ) & TB_HIDEDESC ) == 0 ); + wMenuPopupShow( moveDescM ); + break; + + default: + ; + } + + return C_CONTINUE; +} + + +static void FlipTracks( + coOrd orig, + ANGLE_T angle ) +{ + track_p trk, trk1; + EPINX_T ep, ep1; + + wSetCursor( wCursorWait ); + /*UndoStart( "Move/Rotate Tracks", "move/rotate" );*/ + if (selectedTrackCount <= incrementalDrawLimit) { + DrawMapBoundingBox( FALSE ); + wDrawDelayUpdate( mainD.d, TRUE ); + wDrawDelayUpdate( mapD.d, TRUE ); + } + for ( trk=NULL; TrackIterate(&trk); ) { + if ( !GetTrkSelected(trk) ) + continue; + UndoModify( trk ); + if (selectedTrackCount <= incrementalDrawLimit) { + DrawTrack( trk, &mainD, wDrawColorWhite ); + DrawTrack( trk, &mapD, wDrawColorWhite ); + } + 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 ); + } + } + FlipTrack( trk, orig, angle ); + if (selectedTrackCount <= incrementalDrawLimit) { + DrawTrack( trk, &mainD, wDrawColorBlack ); + DrawTrack( trk, &mapD, wDrawColorBlack ); + } + } + if (selectedTrackCount > incrementalDrawLimit) { + DoRedraw(); + } else { + wDrawDelayUpdate( mainD.d, FALSE ); + wDrawDelayUpdate( mapD.d, FALSE ); + DrawMapBoundingBox( TRUE ); + } + wSetCursor( wCursorNormal ); + UndoEnd(); + InfoCount( trackCount ); + MainRedraw(); +} + + +static STATUS_T CmdFlip( + wAction_t action, + coOrd pos ) +{ + static coOrd pos0; + static coOrd pos1; + static int state; + + switch( action ) { + + case C_START: + state = 0; + if (selectedTrackCount == 0) { + ErrorMessage( MSG_NO_SELECTED_TRK ); + return C_TERMINATE; + } + if (SelectedTracksAreFrozen()) + return C_TERMINATE; + InfoMessage( _("Drag to mark mirror line") ); + break; + case C_DOWN: + state = 1; + if (SelectedTracksAreFrozen()) { + return C_TERMINATE; + } + pos0 = pos1 = pos; + DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); + MainRedraw(); + 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(); + return C_CONTINUE; + case C_UP: + DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); + UndoStart( _("Flip Tracks"), "flip" ); + FlipTracks( pos0, FindAngle( pos0, pos1 ) ); + state = 0; + MainRedraw(); + return C_TERMINATE; + +#ifdef LATER + case C_CANCEL: +#endif + case C_REDRAW: + if ( state == 0 ) + return C_CONTINUE; + DrawLine( &tempD, pos0, pos1, 0, wDrawColorBlack ); + return C_CONTINUE; + + default: + break; + } + return C_CONTINUE; +} + +static STATUS_T SelectArea( + wAction_t action, + coOrd pos ) +{ + static coOrd pos0; + static int state; + static coOrd base, size, lo, hi; + int cnt; + + track_p trk; + + switch (action) { + + case C_START: + state = 0; + return C_CONTINUE; + + case C_DOWN: + case C_RDOWN: + pos0 = pos; + return C_CONTINUE; + + case C_MOVE: + case C_RMOVE: + if (state == 0) { + state = 1; + } else { + DrawHilight( &mainD, base, size ); + } + base = pos0; + size.x = pos.x - pos0.x; + if (size.x < 0) { + size.x = - size.x; + base.x = pos.x; + } + size.y = pos.y - pos0.y; + if (size.y < 0) { + size.y = - size.y; + base.y = pos.y; + } + DrawHilight( &mainD, base, size ); + return C_CONTINUE; + + case C_UP: + case C_RUP: + if (state == 1) { + state = 0; + DrawHilight( &mainD, base, size ); + cnt = 0; + trk = NULL; + 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++; + } + } + } + trk = NULL; + 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) ) { + if (cnt > incrementalDrawLimit) { + selectedTrackCount += (action==C_UP?1:-1); + if (action==C_UP) + SetTrkBits( trk, TB_SELECTED ); + else + ClrTrkBits( trk, TB_SELECTED ); + } else { + SelectOneTrack( trk, action==C_UP ); + } + } + } + } + SelectedTrackCountChange(); + if (cnt > incrementalDrawLimit) + MainRedraw(); + } + return C_CONTINUE; + + case C_CANCEL: + if (state == 1) { + DrawHilight( &mainD, base, size ); + state = 0; + } + break; + + case C_REDRAW: + if (state == 0) + break; + DrawHilight( &mainD, base, size ); + break; + + } + return C_CONTINUE; +} + + +static STATUS_T SelectTrack( + coOrd pos ) +{ + track_p trk; + char msg[STR_SIZE]; + + if ((trk = OnTrack( &pos, TRUE, FALSE )) == NULL) { + return C_CONTINUE; + } + DescribeTrack( trk, msg, sizeof msg ); + InfoMessage( msg ); + if (MyGetKeyState() & WKEY_SHIFT) { + SelectConnectedTracks( trk ); + } else { + SelectOneTrack( trk, !GetTrkSelected(trk) ); + } + return C_CONTINUE; +} + + +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; + } + } + + switch (action) { + case C_START: + InfoMessage( _("Select tracks") ); +#ifdef LATER + if ((!importMove) && selectedTrackCount > 0) { + SetAllTrackSelect( FALSE ); + } +#endif + importMove = FALSE; + SelectArea( action, pos ); + wMenuPushEnable( rotateAlignMI, FALSE ); + break; + + case C_DOWN: + case C_UP: + case C_MOVE: + case C_RDOWN: + case C_RUP: + case C_RMOVE: + case C_REDRAW: + switch (mode) { + case MOVE: + if (SelectedTracksAreFrozen()) { + 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 ); + } + } + break; + case MOVEDESC: + rc = CmdMoveDescription( action, pos ); + break; + case AREA: + rc = SelectArea( action, pos ); + break; + case NONE: + break; + } + if (action == C_UP || action == C_RUP) + mode = AREA; + return rc; + + case wActionMove: + break; + + case C_LCLICK: + switch (mode) { + case MOVE: + case MOVEDESC: + break; + case AREA: + case NONE: + return SelectTrack( pos ); + } + mode = AREA; + break; + + case C_CMDMENU: + if (selectedTrackCount <= 0) { + wMenuPopupShow( selectPopup1M ); + } else { + wMenuPopupShow( selectPopup2M ); + } + return C_CONTINUE; + } + return C_CONTINUE; +} + + +#include "bitmaps/select.xpm" +#include "bitmaps/delete.xpm" +#include "bitmaps/tunnel.xpm" +#include "bitmaps/move.xpm" +#include "bitmaps/rotate.xpm" +#include "bitmaps/flip.xpm" +#include "bitmaps/movedesc.xpm" + + +static void SetMoveMode( char * line ) +{ + long tmp = atol( line ); + moveMode = tmp & 0x0F; + if (moveMode < 0 || moveMode > MAXMOVEMODE) + moveMode = MAXMOVEMODE; + enableMoveDraw = ((tmp&0x10) == 0); +} + + +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 ); + 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 ); + angle_bm[2] = wDrawBitMapCreate( mainD.d, bma0_width, bma0_width, 7, 7, bma0_bits ); + angle_bm[3] = wDrawBitMapCreate( mainD.d, bma45_width, bma45_width, 7, 7, bma45_bits ); + AddPlaybackProc( SETMOVEMODE, (playbackProc_p)SetMoveMode, NULL ); + 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 ); + wMenuSeparatorCreate( selectPopup2M ); + AddRotateMenu( selectPopup2M, QuickRotate ); + rotateAlignMI = wMenuPushCreate( selectPopup2M, "", _("Align"), 0, (wMenuCallBack_p)RotateAlign, NULL ); + ParamRegister( &rescalePG ); +} + + +EXPORT void InitCmdDelete( void ) +{ + wIcon_p icon; + icon = wIconCreatePixMap( delete_xpm ); + AddToolbarButton( "cmdDelete", icon, IC_SELECTED, (wButtonCallBack_p)SelectDelete, 0 ); +#ifdef WINDOWS + wAttachAccelKey( wAccelKey_Del, 0, (wAccelKeyCallBack_p)SelectDelete, NULL ); +#endif +} + +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 InitCmdMoveDescription( wMenu_p menu ) +{ + AddMenuButton( menu, CmdMoveDescription, "cmdMoveLabel", _("Move Description"), wIconCreatePixMap(movedesc_xpm), + LEVEL0, IC_STICKY|IC_POPUP|IC_CMDMENU, ACCL_MOVEDESC, NULL ); +} + + +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 ); + rotateCmdInx = AddMenuButton( menu, CmdRotate, "cmdRotate", _("Rotate"), wIconCreatePixMap(rotate_xpm), + LEVEL0, IC_STICKY|IC_SELECTED|IC_CMDMENU, ACCL_ROTATE, NULL ); + /*flipCmdInx =*/ AddMenuButton( menu, CmdFlip, "cmdFlip", _("Flip"), wIconCreatePixMap(flip_xpm), + LEVEL0, IC_STICKY|IC_SELECTED|IC_CMDMENU, ACCL_FLIP, NULL ); +} |