Main Page   Data Structures   File List   Data Fields   Globals   Related Pages  

linux-gtk/simulation-ui.c

Go to the documentation of this file.
00001 
00012 #include <gtk/gtk.h>
00013 #include <gdk/gdk.h>
00014 #include <zakdef.h>
00015 #include <simulation.h>
00016 #include <ui.h>
00017 #include <globals.h>
00018 #include <main.h>
00019 #include <drawing.h>
00020 #include <string.h>
00021 #include <strings.h>
00022 #include <assert.h>
00023 
00025 static GtkWidget *pw_win;
00026 
00028 static GtkWidget *dw_area;
00029 
00031 struct tag_pmh {
00032         GdkPixmap *allmap; 
00033         GdkPixmap *power; 
00034         GdkPixmap *power_mask; 
00035         GdkPixmap *water; 
00036         GdkPixmap *water_mask; 
00037 } pmh;
00038 
00040 #define SHOW_POWER      1
00041 
00042 #define SHOW_WATER      (SHOW_POWER<<1)
00043 
00045 static int shown_pixmaps;
00046 
00048 GtkWidget *button_power;
00050 GtkWidget *button_water;
00051 
00053 static struct button_list {
00054         GtkWidget       **button; 
00055         int             field; 
00056 } list_buttons[] = {
00057         { &button_power, SHOW_POWER },
00058         { &button_water, SHOW_WATER },
00059         { NULL, 0 }
00060 };
00061 
00067 static void
00068 bpwater_clicked(GtkWidget *widget, gpointer data __attribute__((unused)))
00069 {
00070         int i;
00071         struct button_list *bl;
00072         int newshown_pixmaps = shown_pixmaps;
00073 
00074         for (i = 0; list_buttons[i].button != NULL; i++) {
00075                 bl = list_buttons + i;
00076                 if (*bl->button == widget) {
00077                         if (bl->field == shown_pixmaps) {
00078                                 newshown_pixmaps = 0;
00079                         } else {
00080                                 newshown_pixmaps = bl->field;
00081                         }
00082                 }
00083                 if (bl->field == shown_pixmaps) {
00084                         gtk_toggle_button_set_active(
00085                             GTK_TOGGLE_BUTTON(*bl->button), FALSE);
00086                 }
00087         }
00088         shown_pixmaps = newshown_pixmaps;
00089         gtk_widget_queue_draw(dw_area);
00090 }
00091 
00098 static gint
00099 close_window(GtkWidget *wid __attribute__((unused)),
00100     gpointer data __attribute__((unused)))
00101 {
00102         pw_win = NULL;
00103         return (FALSE);
00104 }
00105 
00106 void
00107 cleanupMap(void)
00108 {
00109         if (pmh.allmap != NULL) g_object_unref(G_OBJECT(pmh.allmap));
00110         if (pmh.power != NULL) g_object_unref(G_OBJECT(pmh.power));
00111         if (pmh.water != NULL) g_object_unref(G_OBJECT(pmh.water));
00112         if (pmh.power_mask != NULL) g_object_unref(G_OBJECT(pmh.power_mask));
00113         if (pmh.water_mask != NULL) g_object_unref(G_OBJECT(pmh.water_mask));
00114         bzero(&pmh, sizeof (pmh));
00115 }
00116 
00118 typedef enum { ccBlank, ccNeed, ccHas } ccr_t;
00119 
00121 static GdkColor colBlank = { 0, 0, 0, 0 };
00123 static GdkColor colNeedPower = { 1, 255, 0, 0 };
00125 static GdkColor colNeedWater = { 1, 0, 0, 255 };
00127 static GdkColor colFull = { 2, 255, 255, 255 };
00128 
00138 static void
00139 updateAMap(Int16 xpos, Int16 ypos, GdkColor *col, ccr_t carry,
00140     GdkDrawable *dw_ori, GdkDrawable *dw_mask)
00141 {
00142         GdkGC *gc;
00143 
00144         if (col == NULL) {
00145                 gc = gdk_gc_new(dw_mask);
00146                 gdk_gc_set_function(gc, GDK_OR);
00147                 if (carry == ccBlank) {
00148                         col = &colFull;
00149                 } else {
00150                         col = &colBlank;
00151                 }
00152                 gdk_gc_set_foreground(gc, &colFull);
00153                 gdk_gc_set_background(gc, &colBlank);
00154                 gdk_draw_rectangle(dw_mask, gc, TRUE, xpos * mapTileSize(),
00155                     ypos * mapTileSize(), mapTileSize(), mapTileSize());
00156                 g_object_unref(gc);
00157         }
00158 
00159         gc = gdk_gc_new(dw_ori);
00160         gdk_gc_set_foreground(gc, col);
00161         gdk_draw_rectangle(dw_ori, gc, TRUE, xpos * mapTileSize(),
00162             ypos * mapTileSize(), mapTileSize(), mapTileSize());
00163         g_object_unref(gc);
00164 }
00165 
00174 static ccr_t
00175 checkCommon(welem_t world, selem_t flag, carryfn_t carry, UInt8 flagbit)
00176 {
00177         if (!carry(world))
00178                 return (ccBlank);
00179         if (flag & flagbit)
00180                 return (ccHas);
00181         return (ccNeed);
00182 }
00183 
00190 static void
00191 updatePower(Int16 xpos, Int16 ypos, ccr_t has_carry)
00192 {
00193         GdkColor *dc = (has_carry == ccNeed) ? &colNeedPower : NULL;
00194         updateAMap(xpos, ypos, dc, has_carry,
00195             GDK_DRAWABLE(pmh.power), GDK_DRAWABLE(pmh.power_mask));
00196 }
00197 
00204 static void
00205 updateWater(Int16 xpos, Int16 ypos, ccr_t has_carry)
00206 {
00207         GdkColor *dc = (has_carry == ccNeed) ? &colNeedWater : NULL;
00208         updateAMap(xpos, ypos, dc, has_carry,
00209             GDK_DRAWABLE(pmh.water), GDK_DRAWABLE(pmh.water_mask));
00210 }
00211 
00215 /*
00216 static void
00217 initMap(void)
00218 {
00219         Int16 xpos;
00220         Int16 ypos;
00221         selem_t flag;
00222         welem_t content, special;
00223         UInt32 worldpos;
00224 
00225         for (xpos = 0; xpos < getMapWidth(); xpos++) {
00226                 for (ypos = 0; ypos < getMapHeight(); ypos++) {
00227                         worldpos = WORLDPOS(xpos, ypos);
00228                         getWorldAndFlag(worldpos, &content, &flag);
00229                         special = GetGraphicNumber(worldpos);
00230                         UIPaintMapZone(xpos, ypos, special,
00231                             GDK_DRAWABLE(pmh.allmap));
00232                         updatePower(xpos, ypos, checkCommon(content, flag,
00233                                     &CarryPower, POWEREDBIT));
00234                         updateWater(xpos, ypos, checkCommon(content, flag,
00235                                     &CarryWater, WATEREDBIT));
00236                 }
00237         }
00238 }
00239 */
00240 
00242 void
00243 doPixPaint(void)
00244 {
00245         GdkDrawable *dwa = drawable_main_get();
00246 
00247         assert(mapTileSize());
00248         assert(getMapWidth());
00249         assert(getMapHeight());
00250         pmh.allmap = gdk_pixmap_new(dwa,
00251             getMapWidth() * mapTileSize(),
00252             getMapHeight() * mapTileSize(), -1);
00253         pmh.power = gdk_pixmap_new(dwa,
00254             getMapWidth() * mapTileSize(),
00255             getMapHeight() * mapTileSize(), -1);
00256         pmh.power_mask = gdk_pixmap_new(dwa,
00257             getMapWidth() * mapTileSize(),
00258             getMapHeight() * mapTileSize(), 1);
00259         pmh.water = gdk_pixmap_new(dwa,
00260             getMapWidth() * mapTileSize(),
00261             getMapHeight() * mapTileSize(), -1);
00262         pmh.water_mask = gdk_pixmap_new(dwa,
00263             getMapWidth() * mapTileSize(),
00264             getMapHeight() * mapTileSize(), 1);
00265         //initMap();
00266 }
00267 
00275 static gint
00276 expose_pw(GtkWidget *area,
00277     GdkEventExpose *event,
00278     gpointer data __attribute__((unused)))
00279 {
00280         GdkGC *gc = gdk_gc_new(area->window);
00281         GdkPixmap *pm_ext = NULL;
00282         GdkPixmap *pm_ovl = NULL;
00283 
00284         gdk_draw_drawable(
00285             area->window,
00286             gc,
00287             pmh.allmap,
00288             event->area.x,
00289             event->area.y,
00290             event->area.x,
00291             event->area.y,
00292             event->area.width,
00293             event->area.height);
00294 
00295         switch (shown_pixmaps) {
00296         case SHOW_POWER:
00297                 pm_ext = pmh.power;
00298                 pm_ovl = pmh.power_mask;
00299                 break;
00300         case SHOW_WATER:
00301                 pm_ext = pmh.water;
00302                 pm_ovl = pmh.water_mask;
00303                 break;
00304         default:
00305                 break;
00306         }
00307         if (pm_ext != NULL) {
00308                 gdk_gc_set_clip_mask(gc, pm_ovl);
00309                 gdk_draw_drawable(
00310                     area->window,
00311                     gc,
00312                     pm_ext,
00313                     event->area.x,
00314                     event->area.y,
00315                     event->area.x,
00316                     event->area.y,
00317                     event->area.width,
00318                     event->area.height);
00319         }
00320 
00321         g_object_unref(gc);
00322 
00323         return (FALSE);
00324 }
00325 
00329 void
00330 showMap(void)
00331 {
00332         GtkWidget *table;
00333 
00334         if (pw_win != NULL) {
00335                 gtk_widget_show(pw_win);
00336                 return;
00337         }
00338 
00339         pw_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00340         gtk_window_set_title(GTK_WINDOW(pw_win), "Power/Water Distribution");
00341         gtk_window_set_skip_taskbar_hint(GTK_WINDOW(pw_win), TRUE);
00342 
00343         g_signal_connect(G_OBJECT(pw_win), "delete_event",
00344             G_CALLBACK(close_window), NULL);
00345 
00346         table = gtk_table_new(2, 2, FALSE);
00347 
00348         button_power = gtk_toggle_button_new_with_label("Power Grid");
00349         button_water = gtk_toggle_button_new_with_label("Water Supply");
00350 
00351         g_signal_connect(G_OBJECT(button_power), "clicked",
00352             G_CALLBACK(bpwater_clicked), NULL);
00353         g_signal_connect(G_OBJECT(button_water), "clicked",
00354             G_CALLBACK(bpwater_clicked), NULL);
00355 
00356         gtk_table_attach(GTK_TABLE(table), button_power, 0, 1, 0, 1, GTK_FILL,
00357             GTK_SHRINK, 2, 2);
00358         gtk_table_attach(GTK_TABLE(table), button_water, 1, 2, 0, 1, GTK_FILL,
00359             GTK_SHRINK, 2, 2);
00360 
00361         dw_area = gtk_drawing_area_new();
00362         gtk_widget_set_size_request(dw_area, getMapWidth() * mapTileSize(),
00363             getMapHeight() * mapTileSize());
00364         gtk_table_attach(GTK_TABLE(table), dw_area, 0, 2, 1, 2, GTK_EXPAND,
00365             GTK_EXPAND, 2, 2);
00366         gtk_container_add(GTK_CONTAINER(pw_win), table);
00367 
00368         gtk_window_set_policy(GTK_WINDOW(pw_win), FALSE, FALSE, TRUE);
00369 
00370         g_signal_connect(G_OBJECT(dw_area), "expose_event",
00371             G_CALLBACK(expose_pw), NULL);
00372 
00373         gtk_widget_show_all(table);
00374         gtk_widget_show(pw_win);
00375 }
00376 
00377 void
00378 UIPaintMapField(UInt16 xpos, UInt16 ypos, welem_t elem)
00379 {
00380         if (pmh.allmap == NULL)
00381                 doPixPaint();
00382 
00383         UIDrawMapZone(xpos, ypos, elem,
00384             GDK_DRAWABLE(pmh.allmap));
00385 }
00386 
00387 void
00388 UIPaintMapStatus(UInt16 xpos, UInt16 ypos, welem_t world, selem_t status)
00389 {
00390         updatePower(xpos, ypos, checkCommon(world, status, &CarryPower,
00391                     POWEREDBIT));
00392         updateWater(xpos, ypos, checkCommon(world, status, &CarryWater,
00393                     WATEREDBIT));
00394 }
00395 
00399 void
00400 resizeMap(void)
00401 {
00402         cleanupMap();
00403         doPixPaint();
00404 }
00405 

Generated on Mon Aug 30 19:44:15 2004 for pocketcity by doxygen1.2.18