00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00040 static const char *cpLServerTxt = "Server";
00041 static const char *cpBConnectTxt = "Connect";
00042
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
00119 gtk_window_set_policy(GTK_WINDOW(gwWindow), TRUE, TRUE, FALSE);
00120
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
00138 gwTable1 = gtk_table_new(2, 2, FALSE);
00139
00140 gtk_box_pack_start(GTK_BOX(gwVBox), gwTable1, FALSE, FALSE, 0);
00141 gtk_widget_show(gwTable1);
00142
00143
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
00158
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
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
00182 gwTable2 = gtk_table_new(2, 1, FALSE);
00183
00184 gtk_box_pack_start(GTK_BOX(gwVBox), gwTable2, FALSE, FALSE, 0);
00185 gtk_widget_show(gwTable2);
00186
00187
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
00214 gtk_box_pack_start(GTK_BOX(gwVBox), gwSWLocate, TRUE, TRUE, 0);
00215
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