Implement sweep selection as alternative for the piece menu
authorH.G. Muller <h.g.muller@hccnet.nl>
Wed, 6 Apr 2011 19:20:30 +0000 (21:20 +0200)
committerArun Persaud <apersaud@lbl.gov>
Thu, 7 Apr 2011 05:21:42 +0000 (22:21 -0700)
When the option -pieceMenu is off, the piece menu will no longer appear
on right-clicks in Edit Position mode. In stead a Pawn of the chosen
color will appear immediately in the clicked square, and vertical
movement of the mouse with the right button down will cycle through
all other pieces defined in the pieceToCharTable of the current variant.
  Setting the side to move is acheived by clicking the correspondig
clock. Clear board can be effected by clicking the clock of the side
that already has the move.

args.h
backend.c
common.h
xboard.c

diff --git a/args.h b/args.h
index 0822aa7..b91d02d 100644 (file)
--- a/args.h
+++ b/args.h
@@ -211,6 +211,7 @@ ArgDescriptor argDescriptors[] = {
   { "pasteSelection", ArgBoolean, (void *) &appData.pasteSelection, XBOARD, (ArgIniType) FALSE },
 
   { "dropMenu", ArgBoolean, (void *) &appData.dropMenu, TRUE, (ArgIniType) FALSE },
+  { "pieceMenu", ArgBoolean, (void *) &appData.pieceMenu, TRUE, (ArgIniType) TRUE },
   { "remoteShell", ArgFilename, (void *) &appData.remoteShell, FALSE, (ArgIniType) REMOTE_SHELL },
   { "rsh", ArgFilename, (void *) &appData.remoteShell, FALSE, INVALID },
   { "remoteUser", ArgString, (void *) &appData.remoteUser, FALSE, INVALID },
index 4044175..ea0d977 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -267,6 +267,7 @@ char chatPartner[MAX_CHAT][MSG_SIZ]; /* [HGM] chat: list of chatting partners */
 extern int chatCount;
 int chattingPartner;
 char marker[BOARD_RANKS][BOARD_FILES]; /* [HGM] marks for target squares */
+ChessSquare pieceSweep = EmptySquare;
 
 /* States for ics_getting_history */
 #define H_FALSE 0
@@ -4811,6 +4812,20 @@ ProcessICSInitScript(f)
 }
 
 
+void
+NextPiece(int step)
+{
+    ChessSquare piece = boards[currentMove][toY][toX];
+    do {
+       pieceSweep += step;
+       if(pieceSweep == EmptySquare) pieceSweep = WhitePawn; // wrap
+       if((int)pieceSweep == -1) pieceSweep = BlackKing;
+       if(!step) step = 1;
+    } while(PieceToChar(pieceSweep) == '.');
+    boards[currentMove][toY][toX] = pieceSweep;
+    DrawPosition(FALSE, boards[currentMove]);
+    boards[currentMove][toY][toX] = piece;
+}
 /* [HGM] Shogi move preprocessor: swap digits for letters, vice versa */
 void
 AlphaRank(char *move, int n)
@@ -5063,15 +5078,18 @@ UnLoadPV()
 void
 MovePV(int x, int y, int h)
 { // step through PV based on mouse coordinates (called on mouse move)
-  int margin = h>>3, step = 0;
+  int margin = h>>3, step = 0, dist;
 
-  if(endPV < 0) return;
   // we must somehow check if right button is still down (might be released off board!)
-  if(y < margin && (abs(x - lastX) > 6 || abs(y - lastY) > 6)) step = 1; else
-  if(y > h - margin && (abs(x - lastX) > 6 || abs(y - lastY) > 6)) step = -1; else
-  if( y > lastY + 6 ) step = -1; else if(y < lastY - 6) step = 1;
+  if(abs(x - lastX) < 7 && abs(y - lastY) < 7) return;
+  if( y > lastY + 2 ) step = -1; else if(y < lastY - 2) step = 1;
   if(!step) return;
   lastX = x; lastY = y;
+
+  if(pieceSweep != EmptySquare) { NextPiece(step); return; }
+  if(endPV < 0) return;
+  if(y < margin) step = 1; else
+  if(y > h - margin) step = -1;
   if(currentMove + step > endPV || currentMove + step < forwardMostMove) step = 0;
   currentMove += step;
   if(currentMove == forwardMostMove) ClearPremoveHighlights(); else
@@ -5731,12 +5749,11 @@ HasPromotionChoice(int fromX, int fromY, int toX, int toY, char *promoChoice)
        *promoChoice = PieceToChar(BlackQueen); // Queen as good as any
        return FALSE;
     }
-    if(autoQueen) { // predetermined
-       if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantLosers)
-            *promoChoice = PieceToChar(BlackKing); // in Suicide Q is the last thing we want
-       else *promoChoice = PieceToChar(BlackQueen);
-       return FALSE;
-    }
+    // give caller the default choice even if we will not make it
+    if(gameInfo.variant == VariantSuicide || gameInfo.variant == VariantGiveaway)
+        *promoChoice = PieceToChar(BlackKing); // in Suicide Q is the last thing we want
+    else *promoChoice = PieceToChar(BlackQueen);
+    if(autoQueen) return FALSE; // predetermined
 
     // suppress promotion popup on illegal moves that are not premoves
     premove = gameMode == IcsPlayingWhite && !WhiteOnMove(currentMove) ||
@@ -6613,16 +6630,25 @@ int RightClick(ClickType action, int x, int y, int *fromX, int *fromY)
 
     xSqr = EventToSquare(x, BOARD_WIDTH);
     ySqr = EventToSquare(y, BOARD_HEIGHT);
-    if (action == Release) UnLoadPV(); // [HGM] pv
+    if (action == Release) {
+       if(pieceSweep != EmptySquare) {
+           EditPositionMenuEvent(pieceSweep, toX, toY);
+           pieceSweep = EmptySquare;
+       } else UnLoadPV(); // [HGM] pv
+    }
     if (action != Press) return -2; // return code to be ignored
     switch (gameMode) {
       case IcsExamining:
        if(xSqr < BOARD_LEFT || xSqr >= BOARD_RGHT) return -1;\r
       case EditPosition:
        if (xSqr == BOARD_LEFT-1 || xSqr == BOARD_RGHT) return -1;\r
-       if (xSqr < 0 || ySqr < 0) return -1;\r
-       whichMenu = 0; // edit-position menu
-       break;
+       if (xSqr < 0 || ySqr < 0) return -1;
+       if(appData.pieceMenu) { whichMenu = 0; break; } // edit-position menu
+       pieceSweep = shiftKey ? BlackPawn : WhitePawn;  // [HGM] sweep: prepare selecting piece by mouse sweep
+       toX = xSqr; toY = ySqr; lastX = x, lastY = y;
+       if(flipView) toX = BOARD_WIDTH - 1 - toX; else toY = BOARD_HEIGHT - 1 - toY;
+       NextPiece(0);
+       return -2;\r
       case IcsObserving:
        if(!appData.icsEngineAnalyze) return -1;
       case IcsPlayingWhite:
@@ -12614,6 +12640,7 @@ ClockClick(int which)
 {      // [HGM] code moved to back-end from winboard.c
        if(which) { // black clock
          if (gameMode == EditPosition || gameMode == IcsExamining) {
+           if(!appData.pieceMenu && blackPlaysFirst) EditPositionMenuEvent(ClearBoard, 0, 0);
            SetBlackToPlayEvent();
          } else if (gameMode == EditGame || shiftKey) {
            AdjustClock(which, -1);
@@ -12623,6 +12650,7 @@ ClockClick(int which)
          }
        } else { // white clock
          if (gameMode == EditPosition || gameMode == IcsExamining) {
+           if(!appData.pieceMenu && !blackPlaysFirst) EditPositionMenuEvent(ClearBoard, 0, 0);
            SetWhiteToPlayEvent();
          } else if (gameMode == EditGame || shiftKey) {
            AdjustClock(which, -1);
index 23f8811..a82fc13 100644 (file)
--- a/common.h
+++ b/common.h
@@ -656,6 +656,7 @@ typedef struct {
     int nrVariations;   /* [HGM] multivar  */
     Boolean dropMenu;   /* [HGM] pv        */
     Boolean markers;    /* [HGM] markers   */
+    Boolean pieceMenu;
 } AppData, *AppDataPtr;
 
 /*  PGN tags (for showing in the game list) */
index 5f4cb0c..079d42b 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -3951,6 +3951,7 @@ void PieceMenuPopup(w, event, params, num_params)
      Cardinal *num_params;
 {
     String whichMenu; int menuNr;
+    shiftKey = strcmp(params[0], "menuW"); // used to indicate black
     if (event->type == ButtonRelease)
         menuNr = RightClick(Release, event->xbutton.x, event->xbutton.y, &pmFromX, &pmFromY);
     else if (event->type == ButtonPress)