Let file chooser show preview of textures on board
authorH.G.Muller <hgm@hgm-xboard.(none)>
Tue, 19 Apr 2016 18:49:03 +0000 (20:49 +0200)
committerH.G.Muller <hgm@hgm-xboard.(none)>
Wed, 20 Apr 2016 08:18:36 +0000 (10:18 +0200)
When browsing for a board texture or piece theme, selecting a file in
the browser will now cause immediate display of the board with that
texture or theme, which will revert if you cancel the choice. Or when
you accept the choice, but cancel the Board dialog.

dialogs.c
dialogs.h
draw.c
draw.h
gtk/xboard.c
gtk/xoptions.c
xaw/xboard.c

index 8624ff4..8b53631 100644 (file)
--- a/dialogs.c
+++ b/dialogs.c
@@ -941,10 +941,10 @@ static Option boardOptions[] = {
 { 0, 0, 200, NULL, (void*) &appData.logoSize, "", NULL, Spin, N_("Logo Size (0=off, requires restart):") },
 { 0,-1, 5, NULL, (void*) &appData.overrideLineGap, "", NULL, Spin, N_("Line Gap (-1 = default for board size):") },
 { 0, 0, 0, NULL, (void*) &appData.useBitmaps, "", NULL, CheckBox, N_("Use Board Textures") },
-{ 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, ".png", NULL, FileName, N_("Light-Squares Texture File:") },
-{ 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, ".png", NULL, FileName, N_("Dark-Squares Texture File:") },
+{ 0, 0, 0, NULL, (void*) &appData.darkBackTextureFile, ".png", (char**)(intptr_t) 1, FileName, N_("Dark-Squares Texture File:") },
+{ 0, 0, 0, NULL, (void*) &appData.liteBackTextureFile, ".png", (char**)(intptr_t) 2, FileName, N_("Light-Squares Texture File:") },
 { 0, 0, 0, NULL, (void*) &appData.trueColors, "", NULL, CheckBox, N_("Use external piece bitmaps with their own colors") },
-{ 0, 0, 0, NULL, (void*) &appData.pieceDirectory, "", NULL, PathName, N_("Directory with Pieces Images:") },
+{ 0, 0, 0, NULL, (void*) &appData.pieceDirectory, "",  (char**)(intptr_t) 3, PathName, N_("Directory with Pieces Images:") },
 { 0, 0, 0, NULL, (void*) &BoardOptionsOK, "", NULL, EndMark , "" }
 };
 
index a0b8cf6..99b01e4 100644 (file)
--- a/dialogs.h
+++ b/dialogs.h
@@ -211,6 +211,8 @@ void WidgetEcho P((Option *opt, int n));
 int  ErrorOK P((int n));
 void ApplyFont P((Option *opt, char *font));
 void LockBoardSize P((int after));
+void Preview P((int n, char *s));
+void DrawPosition P((int fullRedraw, Board b));
 
 
 // in ngamelist.c
diff --git a/draw.c b/draw.c
index 82072bf..bbe4a79 100644 (file)
--- a/draw.c
+++ b/draw.c
@@ -220,7 +220,7 @@ InitDrawingSizes (BoardSize boardSize, int flags)
        squareSize = ((squareSize + lineGap) * oldNrOfFiles + 0.5*BOARD_WIDTH) / BOARD_WIDTH; // keep total width fixed
        if(appData.overrideLineGap < 0) lineGap = squareSize < 37 ? 1 : squareSize < 59 ? 2 : squareSize < 116 ? 3 : 4;
         squareSize -= lineGap;
-       CreatePNGPieces();
+       CreatePNGPieces(appData.pieceDirectory);
         CreateGrid();
     }
     oldNrOfFiles = BOARD_WIDTH;
@@ -389,7 +389,7 @@ LoadSVG (char *dir, int color, int piece, int retry)
 }
 
 static void
-ScaleOnePiece (int color, int piece)
+ScaleOnePiece (int color, int piece, char *pieceDir)
 {
   float w, h;
   char buf[MSG_SIZ];
@@ -401,11 +401,11 @@ ScaleOnePiece (int color, int piece)
   svgPieces[color][piece] = LoadSVG("", color, piece, 0); // this fills pngPieceImages if we had cached svg with bitmap of wanted size
 
   if(!pngPieceImages[color][piece]) { // we don't have cached bitmap (implying we did not have cached svg)
-    if(*appData.pieceDirectory) { // user specified piece directory
-      snprintf(buf, MSG_SIZ, "%s/%s%s.png", appData.pieceDirectory, color ? "Black" : "White", pngPieceNames[piece]);
+    if(*pieceDir) { // user specified piece directory
+      snprintf(buf, MSG_SIZ, "%s/%s%s.png", pieceDir, color ? "Black" : "White", pngPieceNames[piece]);
       img = cairo_image_surface_create_from_png (buf); // try if there are png pieces there
       if(cairo_surface_status(img) != CAIRO_STATUS_SUCCESS) { // there were not
-       svgPieces[color][piece] = LoadSVG(appData.pieceDirectory, color, piece, 0); // so try if he has svg there
+       svgPieces[color][piece] = LoadSVG(pieceDir, color, piece, 0); // so try if he has svg there
       } else pngPieceImages[color][piece] = img;
     }
   }
@@ -438,7 +438,7 @@ ScaleOnePiece (int color, int piece)
   cairo_paint (cr);
   cairo_destroy (cr);
 
-  if(!appData.trueColors || !*appData.pieceDirectory) { // operate on bitmap to color it (king-size hack...)
+  if(!appData.trueColors || !*pieceDir) { // operate on bitmap to color it (king-size hack...)
     int stride = cairo_image_surface_get_stride(cs)/4;
     int *buf = (int *) cairo_image_surface_get_data(cs);
     int i, j, p;
@@ -464,13 +464,12 @@ ScaleOnePiece (int color, int piece)
 }
 
 void
-CreatePNGPieces ()
+CreatePNGPieces (char *pieceDir)
 {
   int p;
-
   for(p=0; pngPieceNames[p]; p++) {
-    ScaleOnePiece(0, p);
-    ScaleOnePiece(1, p);
+    ScaleOnePiece(0, p, pieceDir);
+    ScaleOnePiece(1, p, pieceDir);
   }
   SelectPieces(gameInfo.variant);
 }
@@ -478,25 +477,53 @@ CreatePNGPieces ()
 void
 CreateAnyPieces (int p)
 {   // [HGM] taken out of main
-    if(p) CreatePNGPieces();
+    if(p) CreatePNGPieces(appData.pieceDirectory);
     CreatePNGBoard(appData.liteBackTextureFile, 1);
     CreatePNGBoard(appData.darkBackTextureFile, 0);
 }
 
-void
-InitDrawingParams (int reloadPieces)
+static void
+ClearPieces ()
 {
     int i, p;
-    if(reloadPieces)
     for(i=0; i<2; i++) for(p=0; p<BlackPawn; p++) {
        if(pngPieceImages[i][p]) cairo_surface_destroy(pngPieceImages[i][p]);
        pngPieceImages[i][p] = NULL;
        if(svgPieces[i][p]) rsvg_handle_close(svgPieces[i][p], NULL);
        svgPieces[i][p] = NULL;
     }
+}
+
+void
+InitDrawingParams (int reloadPieces)
+{
+    if(reloadPieces) ClearPieces();
     CreateAnyPieces(1);
 }
 
+void
+Preview (int n, char *s)
+{
+    static Boolean changed[4];
+    changed[n] = TRUE;
+    switch(n) {
+      case 0: // restore true setting
+       if(changed[3]) ClearPieces();
+       CreateAnyPieces(changed[3]); // recomputes textures and (optionally) pieces
+       for(n=0; n<4; n++) changed[n] = FALSE;
+       break;
+      case 1: 
+      case 2:
+       CreatePNGBoard(s, n-1);
+       break;
+      case 3:
+       ClearPieces();
+       CreatePNGPieces(s);
+       break;
+    }
+    DrawPosition(TRUE, NULL);
+}
+
 // [HGM] seekgraph: some low-level drawing routines (by JC, mostly)
 
 float
diff --git a/draw.h b/draw.h
index 1d1511f..03407af 100644 (file)
--- a/draw.h
+++ b/draw.h
@@ -63,7 +63,7 @@ extern int lineGap, squareSize;
 // defined in draw.c
 void CreateGCs P((int redo));
 void CreateAnyPieces P((int p));
-void CreatePNGPieces P((void));
+void CreatePNGPieces P((char *pieceDir));
 void CreateGrid P((void));
 void DrawSegment P((int x, int y, int *lastX, int *lastY, int p));
 void DrawRectangle P((int left, int top, int right, int bottom, int side, int style));
index 5ad75b1..7c515a9 100644 (file)
@@ -1738,7 +1738,7 @@ ReSize (WindowPlacement *wp)
 #endif
        if(sqx != squareSize && !first) {
            squareSize = sqx; // adopt new square size
-           CreatePNGPieces(); // make newly scaled pieces
+           CreatePNGPieces(appData.pieceDirectory); // make newly scaled pieces
            InitDrawingSizes(0, 0); // creates grid etc.
        } else ResizeBoardWindow(BOARD_WIDTH * (squareSize + lineGap) + lineGap, BOARD_HEIGHT * (squareSize + lineGap) + lineGap, 0);
        w = BOARD_WIDTH * (squareSize + lineGap) + lineGap;
index 3cf123e..3684bf8 100644 (file)
@@ -845,6 +845,8 @@ MemoEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata)
 #endif
 }
 
+int messedUp;
+
 int
 PopDown (DialogClass n)
 {
@@ -874,6 +876,7 @@ PopDown (DialogClass n)
     RaiseWindow(parents[n]); // automatic in GTK?
     if(parents[n] == BoardWindow) XtSetKeyboardFocus(shellWidget, formWidget); // also automatic???
 #endif
+    if(messedUp) Preview(0, NULL); messedUp = FALSE; // Board Options dialog can need this to cancel preview
     return 1;
 }
 
@@ -1101,13 +1104,25 @@ void GenericCallback(GtkWidget *widget, gpointer gdata)
     shells[dlg] = oldSh; // in case of multiple instances, restore previous (as this one could be popped down now)
 }
 
+int
+BrowseCallback (GtkFileChooser *chooser, gpointer data)
+{
+    char *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));
+    Option *opt = currentOption + (int)(intptr_t) data;
+    int n = (int) (intptr_t) opt->choice;
+    Preview(n, name);
+    messedUp = TRUE;
+    if(name) g_free(name);
+    return FALSE;
+}
+
 void BrowseGTK(GtkWidget *widget, gpointer gdata)
 {
     GtkWidget *entry;
     GtkWidget *dialog;
     GtkFileFilter *gtkfilter;
     GtkFileFilter *gtkfilter_all;
-    int opt_i = (intptr_t) gdata;
+    int n, opt_i = (intptr_t) gdata;
     GtkFileChooserAction fc_action;
     char buf[MSG_SIZ];
 
@@ -1162,6 +1177,11 @@ void BrowseGTK(GtkWidget *widget, gpointer gdata)
     else
       gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter_all);
 
+    messedUp = FALSE;
+    n = (int)(intptr_t) currentOption[opt_i].choice;
+    if (n && !currentCps)
+      g_signal_connect (GTK_DIALOG (dialog), "selection-changed", G_CALLBACK(BrowseCallback), (gpointer)(intptr_t) opt_i);
+
     if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
       {
         char *filename;
@@ -1171,7 +1191,10 @@ void BrowseGTK(GtkWidget *widget, gpointer gdata)
        StartDir(filter, filename); // back to original, and remember this one
         g_free (filename);
       }
-    else StartDir(filter, ""); // change back to original directory
+    else {
+       StartDir(filter, ""); // change back to original directory
+       if(n && messedUp) Preview(n, old); // undo any board preview of the parameter browsed for
+    }
     gtk_widget_destroy (dialog);
     dialog = NULL;
 }
index 4fb562a..1c3ffc7 100644 (file)
@@ -1709,7 +1709,7 @@ ReSize (WindowPlacement *wp)
        if(sqy < sqx) sqx = sqy;
        if(sqx != squareSize) {
            squareSize = sqx; // adopt new square size
-           CreatePNGPieces(); // make newly scaled pieces
+           CreatePNGPieces(appData.pieceDirectory); // make newly scaled pieces
            InitDrawingSizes(0, 0); // creates grid etc.
        } else ResizeBoardWindow(BOARD_WIDTH * (squareSize + lineGap) + lineGap, BOARD_HEIGHT * (squareSize + lineGap) + lineGap, 0);
        w = BOARD_WIDTH * (squareSize + lineGap) + lineGap;