Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

GUILocate.cc

Go to the documentation of this file.
00001 /*
00002 
00003     GUI for locating
00004     Copyright (C) 2000-2001 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 */
00021 
00022 
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <signal.h>
00026 #include <unistd.h>
00027 #include <math.h>
00028 #include <float.h>
00029 
00030 #include <gtk/gtk.h>
00031 #include <gdk/gdkrgb.h>
00032 
00033 #include "GUILocate.hh"
00034 
00035 
00036 G_LOCK_DEFINE_STATIC(gmInputMutex);
00037 
00038 static const char *cpWindowTxt = "Locate";
00039 // Table 1
00040 static const char *cpLServerTxt = "Server";
00041 static const char *cpBConnectTxt = "Connect";
00042 // Table 2
00043 static const char *cpLPaletteTxt = "Palette";
00044 static const char *cpaLPaletteMenu[] = { "BW", "HSV", "Light", "Temp",
00045     "Dir", "Green", "Green2", "PureGreen", "WB" };
00046 
00047 clGUILocate GUILocate;
00048 
00049 
00050 int main (int argc, char *argv[])
00051 {
00052     signal(SIGPIPE, SIG_IGN);
00053     signal(SIGFPE, SIG_IGN);
00054     return GUILocate.Main(&argc, &argv);
00055 }
00056 
00057 
00058 gboolean WrapOnDelete (GtkWidget *gwSender, GdkEvent *geEvent,
00059     gpointer gpData)
00060 {
00061     return GUILocate.OnDelete(gwSender, geEvent, gpData);
00062 }
00063 
00064 
00065 void WrapOnConnectClick (GtkButton *gbSender, gpointer gpData)
00066 {
00067     GUILocate.OnConnectClick(gbSender, gpData);
00068 }
00069 
00070 
00071 void WrapOnPaletteActivate (GtkMenuItem *gmiSender, gpointer gpData)
00072 {
00073     GUILocate.OnPaletteActivate(gmiSender, gpData);
00074 }
00075 
00076 
00077 gboolean WrapOnLocateExpose (GtkWidget *gwSender, GdkEventExpose *geeEvent,
00078     gpointer gpData)
00079 {
00080     return GUILocate.OnLocateExpose(gwSender, geeEvent, gpData);
00081 }
00082 
00083 
00084 gboolean WrapOnLocateMotion (GtkWidget *gwSender, GdkEventMotion *gemEvent,
00085     gpointer gpData)
00086 {
00087     return GUILocate.OnLocateMotion(gwSender, gemEvent, gpData);
00088 }
00089 
00090 
00091 void WrapOnGdkInput (gpointer gpData, gint iSource,
00092     GdkInputCondition gicCondition)
00093 {
00094     GUILocate.OnGdkInput(gpData, iSource, gicCondition);
00095 }
00096 
00097 
00098 bool clGUILocate::GetCfg ()
00099 {
00100     Cfg.SetFileName(GUILOC_CFGFILE);
00101     if (Cfg.GetInt("Palette", &iPalette))
00102     {
00103         OnPaletteActivate(NULL, GINT_TO_POINTER(iPalette));
00104     }
00105     else
00106     {
00107         iPalette = 0;
00108         Pal.GenBW();
00109     }
00110     return true;
00111 }
00112 
00113 
00114 bool clGUILocate::Build ()
00115 {
00116     gwWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00117     gtk_window_set_title(GTK_WINDOW(gwWindow), cpWindowTxt);
00118     // shrink, grow, auto-shrink
00119     gtk_window_set_policy(GTK_WINDOW(gwWindow), TRUE, TRUE, FALSE);
00120     // homogenous, spacing
00121     gwVBox = gtk_vbox_new(FALSE, GUILOC_WSPACING);
00122     gtk_container_add(GTK_CONTAINER(gwWindow), gwVBox);
00123     gtk_widget_show(gwVBox);
00124     if (!BuildTable1()) return false;
00125     if (!BuildTable2()) return false;
00126     if (!BuildLocate()) return false;
00127     if (!ConnectSignals()) return false;
00128     gtk_widget_show(gwWindow);
00129     if (!BuildDrawingPrims()) return false;
00130     gdk_window_set_cursor(gwDALocate->window, gcCrossHair);
00131     return true;
00132 }
00133 
00134 
00135 bool clGUILocate::BuildTable1 ()
00136 {
00137     // rows, columns, homogenous
00138     gwTable1 = gtk_table_new(2, 2, FALSE);
00139     // box, child, expand, fill, padding
00140     gtk_box_pack_start(GTK_BOX(gwVBox), gwTable1, FALSE, FALSE, 0);
00141     gtk_widget_show(gwTable1);
00142 
00143     // - Label & Combo: Server
00144     gwLServer = gtk_label_new(cpLServerTxt);
00145     gtk_label_set_justify(GTK_LABEL(gwLServer), GTK_JUSTIFY_LEFT);
00146     gtk_table_attach(GTK_TABLE(gwTable1), gwLServer,
00147         0, 1, 0, 1,
00148         (GtkAttachOptions) (GTK_FILL|GTK_EXPAND|GTK_SHRINK),
00149         (GtkAttachOptions) 0,
00150         GUILOC_WSPACING / 2, 0);
00151     gtk_widget_show(gwLServer);
00152     gwCServer = gtk_combo_new();
00153     gtk_entry_set_max_length(GTK_ENTRY(GTK_COMBO(gwCServer)->entry),
00154         GUILOC_SERVER_MAXLEN);
00155     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(gwCServer)->entry),
00156         "127.0.0.1:30002");
00157     // table, child, left attach, right attach, top attach, bottom attach,
00158     // x-options, y-options, x-padding, y-padding
00159     gtk_table_attach(GTK_TABLE(gwTable1), gwCServer,
00160         0, 1, 1, 2,
00161         (GtkAttachOptions) (GTK_FILL|GTK_EXPAND|GTK_SHRINK),
00162         (GtkAttachOptions) 0,
00163         GUILOC_WSPACING / 2, 0);
00164     gtk_widget_show(gwCServer);
00165     GtkUtils.ComboListFromFile(gwCServer, &glServer, GUILOC_HOSTFILE);
00166 
00167     // - Button: Connect
00168     gwBConnect = gtk_button_new_with_label(cpBConnectTxt);
00169     gtk_table_attach(GTK_TABLE(gwTable1), gwBConnect,
00170         1, 2, 1, 2,
00171         (GtkAttachOptions) GTK_FILL, (GtkAttachOptions) 0,
00172         GUILOC_WSPACING / 2, 0);
00173     gtk_widget_show(gwBConnect);
00174 
00175     return true;
00176 }
00177 
00178 
00179 bool clGUILocate::BuildTable2 ()
00180 {
00181     // rows, columns, homogenous
00182     gwTable2 = gtk_table_new(2, 1, FALSE);
00183     // box, child, expand, fill, padding
00184     gtk_box_pack_start(GTK_BOX(gwVBox), gwTable2, FALSE, FALSE, 0);
00185     gtk_widget_show(gwTable2);
00186 
00187     // Label & OptionMenu: Palette
00188     gwLPalette = gtk_label_new(cpLPaletteTxt);
00189     gtk_label_set_justify(GTK_LABEL(gwLPalette), GTK_JUSTIFY_LEFT);
00190     gtk_table_attach(GTK_TABLE(gwTable2), gwLPalette,
00191         0, 1, 0, 1,
00192         (GtkAttachOptions) GTK_FILL, (GtkAttachOptions) 0,
00193         GUILOC_WSPACING / 2, 0);
00194     gtk_widget_show(gwLPalette);
00195     gwOMPalette = gtk_option_menu_new();
00196     gtk_table_attach(GTK_TABLE(gwTable2), gwOMPalette,
00197         0, 1, 1, 2,
00198         (GtkAttachOptions) GTK_FILL, (GtkAttachOptions) 0,
00199         GUILOC_WSPACING / 2, 0);
00200     gtk_widget_show(gwOMPalette);
00201     GtkUtils.BuildOptionMenu(gwOMPalette, &gwMPalette, gwaMIPalette,
00202         cpaLPaletteMenu, GUILOC_PALETTE_ITEMS);
00203     gtk_option_menu_set_history(GTK_OPTION_MENU(gwOMPalette),
00204         (guint) iPalette);
00205         
00206     return true;
00207 }
00208 
00209 
00210 bool clGUILocate::BuildLocate ()
00211 {
00212     gwSWLocate = gtk_scrolled_window_new(NULL, NULL);
00213     // box, child, expand, fill, padding
00214     gtk_box_pack_start(GTK_BOX(gwVBox), gwSWLocate, TRUE, TRUE, 0);
00215     // hpolicy, vpolicy
00216     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gwSWLocate),
00217         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
00218     gtk_widget_show(gwSWLocate);
00219 
00220     gwDALocate = gtk_drawing_area_new();
00221     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(gwSWLocate),
00222         gwDALocate);
00223     gtk_widget_show(gwDALocate);
00224 
00225     return true;
00226 }
00227 
00228 
00229 bool clGUILocate::ConnectSignals ()
00230 {
00231     int iWidgetCntr;
00232 
00233     gtk_signal_connect(GTK_OBJECT(gwWindow), "delete-event",
00234         GTK_SIGNAL_FUNC(WrapOnDelete), NULL);
00235 
00236     gtk_signal_connect(GTK_OBJECT(gwBConnect), "clicked",
00237         GTK_SIGNAL_FUNC(WrapOnConnectClick), NULL);
00238 
00239     gtk_widget_add_events(gwDALocate, GDK_POINTER_MOTION_MASK);
00240     gtk_signal_connect(GTK_OBJECT(gwDALocate), "expose-event",
00241         GTK_SIGNAL_FUNC(WrapOnLocateExpose), NULL);
00242     gtk_signal_connect(GTK_OBJECT(gwDALocate), "motion-notify-event",
00243         GTK_SIGNAL_FUNC(WrapOnLocateMotion), NULL);
00244 
00245     for (iWidgetCntr = 0; iWidgetCntr < GUILOC_PALETTE_ITEMS; iWidgetCntr++)
00246     {
00247         gtk_signal_connect(GTK_OBJECT(gwaMIPalette[iWidgetCntr]), "activate",
00248             GTK_SIGNAL_FUNC(WrapOnPaletteActivate), 
00249             GINT_TO_POINTER(iWidgetCntr));
00250     }
00251 
00252     return true;
00253 }
00254 
00255 
00256 bool clGUILocate::BuildDrawingPrims ()
00257 {
00258     ggcLocateBG = gdk_gc_new(gwDALocate->window);
00259     gdk_rgb_gc_set_foreground(ggcLocateBG, GUILOC_LOCATE_BG);
00260     gdk_rgb_gc_set_background(ggcLocateBG, GUILOC_LOCATE_BG);
00261     gdk_gc_set_function(ggcLocateBG, GDK_COPY);
00262     gdk_gc_set_fill(ggcLocateBG, GDK_SOLID);
00263 
00264     ggcLocateFG = gdk_gc_new(gwDALocate->window);
00265     gdk_rgb_gc_set_foreground(ggcLocateFG, GUILOC_LOCATE_FG);
00266     gdk_rgb_gc_set_background(ggcLocateFG, GUILOC_LOCATE_BG);
00267     gdk_gc_set_function(ggcLocateFG, GDK_COPY);
00268     gdk_gc_set_fill(ggcLocateFG, GDK_SOLID);
00269 
00270     gcCrossHair = gdk_cursor_new(GDK_CROSSHAIR);
00271 
00272     return true;
00273 }
00274 
00275 
00276 bool clGUILocate::ConnectToServer (const char *cpHostAddr, int iHostPort)
00277 {
00278     int iSockH;
00279     char cpHeader[GLOBAL_HEADER_LEN];
00280 
00281     iSockH = SClient.Connect(cpHostAddr, NULL, iHostPort);
00282     if (iSockH < 0) return false;
00283     SOp.SetHandle(iSockH);
00284     if (SOp.ReadN(cpHeader, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00285     {
00286         g_print("Header receive failed!\n");
00287         return false;
00288     }
00289     Msg.GetHeader(cpHeader, &sHdr);
00290     return true;
00291 }
00292 
00293 
00294 void clGUILocate::DisplayResults ()
00295 {
00296     int iValue;
00297     int iMaxValue;
00298     long lDataCntr;
00299     long lDataCount = sRes.lPointCount;
00300     unsigned int *ipRes = ResFrame;
00301     GDT *fpRes = ResMatrix;
00302     GtkAdjustment *gaHScrollBar;
00303     GtkAdjustment *gaVScrollBar;
00304 
00305     iMaxValue = Pal.Size() - 1;
00306     for (lDataCntr = 0; lDataCntr < lDataCount; lDataCntr++)
00307     {
00308         iValue = (int) (fpRes[lDataCntr] * iMaxValue + (GDT) 0.5);
00309         if (iValue < 0) iValue = 0;
00310         else if (iValue > iMaxValue) iValue = iMaxValue;
00311         ipRes[lDataCntr] = Pal[iValue];
00312     }
00313     gaHScrollBar = gtk_scrolled_window_get_hadjustment(
00314         GTK_SCROLLED_WINDOW(gwSWLocate));
00315     gaVScrollBar = gtk_scrolled_window_get_vadjustment(
00316         GTK_SCROLLED_WINDOW(gwSWLocate));
00317     if (gaHScrollBar == NULL || gaVScrollBar == NULL)
00318     {
00319         gdk_draw_rgb_32_image(gwDALocate->window, ggcLocateFG,
00320             0, 0, sHdr.iWidth, sHdr.iHeight,
00321             GDK_RGB_DITHER_NONE,
00322             ResFrame,
00323             sHdr.iWidth * sizeof(unsigned int));
00324     }
00325     else
00326     {
00327         int iPosX = (int) gaHScrollBar->value;
00328         int iPosY = (int) gaVScrollBar->value;
00329         int iPosW = (int) gaHScrollBar->page_size;
00330         int iPosH = (int) gaVScrollBar->page_size;
00331 
00332         if (iPosX >= sHdr.iWidth || iPosY >= sHdr.iHeight) return;
00333         if (iPosX + iPosW > sHdr.iWidth) iPosW = sHdr.iWidth - iPosX;
00334         if (iPosY + iPosH > sHdr.iHeight) iPosH = sHdr.iHeight - iPosY;
00335 
00336         gdk_draw_rgb_32_image(gwDALocate->window, ggcLocateFG,
00337             iPosX, iPosY, iPosW, iPosH,
00338             GDK_RGB_DITHER_NONE,
00339             (guchar *) &ipRes[iPosY * sHdr.iWidth + iPosX],
00340             sHdr.iWidth * sizeof(unsigned int));
00341     }
00342 }
00343 
00344 
00345 clGUILocate::clGUILocate ()
00346 {
00347     bRun = true;
00348     bConnected = false;
00349 }
00350 
00351 
00352 clGUILocate::~clGUILocate ()
00353 {
00354 }
00355 
00356 
00357 int clGUILocate::Main (int *ipArgC, char ***cppArgV)
00358 {
00359     g_print("%s GUI v%i.%i.%i\n", cpWindowTxt,
00360         GUILOC_VER_MAJ, GUILOC_VER_MIN, GUILOC_VER_PL);
00361     g_print("Copyright (C) 2000-2001 Jussi Laako\n\n");
00362     g_print("Gtk+ version %i.%i.%i\n", gtk_major_version, gtk_minor_version,
00363         gtk_micro_version);
00364     g_print("Locale set to %s\n", gtk_set_locale());
00365     gtk_init(ipArgC, cppArgV);
00366     gdk_rgb_init();
00367     gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
00368     gtk_widget_set_default_visual(gdk_rgb_get_visual());
00369     if (!GetCfg()) return 1;
00370     if (!Build()) return 1;
00371     gtk_main();
00372     return 0;
00373 }
00374 
00375 
00376 gboolean clGUILocate::OnDelete (GtkWidget *gwSender, GdkEvent *geEvent,
00377     gpointer gpData)
00378 {
00379     bRun = false;
00380     gtk_main_quit();
00381     return TRUE;
00382 }
00383 
00384 
00385 void clGUILocate::OnConnectClick (GtkButton *gbSender, gpointer gpData)
00386 {
00387     char **cpaServerAddr;
00388 
00389     if (bConnected)
00390     {
00391         gdk_input_remove(iGdkInputTag);
00392         SOp.Close();
00393     }
00394     cpaServerAddr = g_strsplit(
00395         gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(gwCServer)->entry)),
00396         ":", 2);
00397     if (cpaServerAddr[0] != NULL && cpaServerAddr[1] != NULL)
00398     {
00399         g_print("\nConnecting to %s port %s...\n", cpaServerAddr[0],
00400             cpaServerAddr[1]);
00401         if (ConnectToServer(cpaServerAddr[0], atoi(cpaServerAddr[1])))
00402         {
00403             bConnected = true;
00404             g_print("OK\n");
00405             iMsgSize = GLOBAL_HEADER_LEN + 
00406                 sHdr.iWidth * sHdr.iHeight * sizeof(GDT);
00407             ResMsg.Size(iMsgSize);
00408             ResMatrix.Size(sHdr.iWidth * sHdr.iHeight * sizeof(GDT));
00409             ResFrame.Size(sHdr.iWidth * sHdr.iHeight * sizeof(unsigned int));
00410             gtk_drawing_area_size(GTK_DRAWING_AREA(gwDALocate),
00411                 sHdr.iWidth, sHdr.iHeight);
00412             iGdkInputTag = gdk_input_add(SOp.GetHandle(), GDK_INPUT_READ,
00413                 WrapOnGdkInput, NULL);
00414         }
00415         else
00416         {
00417             g_print("Failed to connect to specified server!\n");
00418         }
00419     }
00420     else
00421     {
00422         g_print(
00423             "\nIncorrect server address format. Format: <server>:<port>\n");
00424     }
00425     g_strfreev(cpaServerAddr);
00426 }
00427 
00428 
00429 void clGUILocate::OnPaletteActivate (GtkMenuItem *gmiSender, gpointer gpData)
00430 {
00431     iPalette = GPOINTER_TO_INT(gpData);
00432     switch (iPalette)
00433     {
00434         case GUILOC_PAL_BW:
00435             Pal.GenBW();
00436             break;
00437         case GUILOC_PAL_HSV:
00438             Pal.GenHSV();
00439             break;
00440         case GUILOC_PAL_LIGHT:
00441             Pal.GenLight();
00442             break;
00443         case GUILOC_PAL_TEMP:
00444             Pal.GenTemp();
00445             break;
00446         case GUILOC_PAL_DIR:
00447             Pal.GenDir();
00448             break;
00449         case GUILOC_PAL_GREEN:
00450             Pal.GenGreen();
00451             break;
00452         case GUILOC_PAL_GREEN2:
00453             Pal.GenGreen2();
00454             break;
00455         case GUILOC_PAL_PUREGREEN:
00456             Pal.GenPureGreen();
00457             break;
00458         case GUILOC_PAL_WB:
00459             Pal.GenWB();
00460             break;
00461         default:
00462             g_print("Error: Unknown palette\n");
00463     }
00464 }
00465 
00466 
00467 gboolean clGUILocate::OnLocateExpose (GtkWidget *gwSender, 
00468     GdkEventExpose *geeEvent, gpointer gpData)
00469 {
00470     int iAreaW;
00471     int iAreaH;
00472     unsigned int *ipFrame = ResFrame;
00473 
00474     if (geeEvent->area.x >= sHdr.iWidth ||
00475         geeEvent->area.y >= sHdr.iHeight) return TRUE;
00476 
00477     if ((geeEvent->area.x + geeEvent->area.width) <= sHdr.iWidth) 
00478         iAreaW = geeEvent->area.width;
00479     else
00480         iAreaW = sHdr.iWidth - geeEvent->area.x;
00481 
00482     if ((geeEvent->area.y + geeEvent->area.height) <= sHdr.iHeight)
00483         iAreaH = geeEvent->area.height;
00484     else
00485         iAreaH = sHdr.iHeight - geeEvent->area.y;
00486 
00487     gdk_draw_rgb_32_image(gwDALocate->window, ggcLocateFG,
00488         geeEvent->area.x, geeEvent->area.y, 
00489         iAreaW, iAreaH, 
00490         GDK_RGB_DITHER_NONE,
00491         (guchar *) &ipFrame[geeEvent->area.y * sHdr.iWidth + geeEvent->area.x],
00492         sHdr.iWidth * sizeof(unsigned int));
00493     return TRUE;
00494 }
00495 
00496 
00497 gboolean clGUILocate::OnLocateMotion (GtkWidget *gwSender, 
00498     GdkEventMotion *gemEvent, gpointer gpData)
00499 {
00500     return TRUE;
00501 }
00502 
00503 
00504 void clGUILocate::OnGdkInput (gpointer gpData, gint iSource,
00505     GdkInputCondition gicCondition)
00506 {
00507     if (!bRun) return;
00508     G_LOCK(gmInputMutex);
00509     while (SOp.ReadSelect(0))
00510     {
00511         if (SOp.ReadN(ResMsg, iMsgSize) < iMsgSize)
00512         {
00513             gdk_input_remove(iGdkInputTag);
00514             SOp.Close();
00515             bConnected = false;
00516             g_print(
00517                 "Error occurred while receiving data, dropped connection.");
00518             break;
00519         }
00520         Msg.GetResult(ResMsg, &sRes, (GDT *) ResMatrix);
00521         DisplayResults();
00522     }
00523     G_UNLOCK(gmInputMutex);
00524 }
00525 

Generated on Sun Oct 26 19:11:20 2003 for HASAS by doxygen 1.3.3