shapegroup.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2002 The Exult Team
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #  include <config.h>
00027 #endif
00028 
00029 #include <cassert>
00030 #include <fstream>
00031 #include <gdk/gdkkeysyms.h>
00032 #include "shapegroup.h"
00033 #include "Flex.h"
00034 #include "utils.h"
00035 #include "exceptions.h"
00036 #include "studio.h"
00037 #include "objbrowse.h"
00038 #include "shapefile.h"
00039 
00040 using std::vector;
00041 using std::ios;
00042 using std::string;
00043 using std::cout;
00044 using std::endl;
00045 using EStudio::Alert;
00046 
00047 /*
00048  *  Create an empty group.
00049  */
00050 
00051 Shape_group::Shape_group
00052   (
00053   const char *nm,     // Name.  Copied.
00054   Shape_group_file *f
00055   ) : name(nm), file(f)
00056   {
00057   }
00058 
00059 /*
00060  *  Remove i'th entry.
00061  */
00062 
00063 void Shape_group::del
00064   (
00065   int i
00066   )
00067   { 
00068   assert(i >= 0 && i < size());
00069   std::vector<int>::erase(begin() + i); 
00070   file->modified = true;
00071   }
00072 
00073 /*
00074  *  Swap two entries.
00075  */
00076 
00077 void Shape_group::swap
00078   (
00079   int i       // Lower one.
00080   )
00081   {
00082   int x0 = (*this)[i];
00083   (*this)[i] = (*this)[i + 1];
00084   (*this)[i + 1] = x0;
00085   file->modified = true;
00086   }
00087 
00088 /*
00089  *  Add a new entry if not already there.
00090  */
00091 
00092 void Shape_group::add
00093   (
00094   int id
00095   )
00096   {
00097   for (vector<int>::const_iterator it = begin(); it != end(); ++it)
00098     if ((*it) == id)
00099       return;   // Already there.
00100   push_back(id);
00101   file->modified = true;
00102   }
00103 
00104 /*
00105  *  Init. and read in (if it exists) a groups file.
00106  */
00107 
00108 Shape_group_file::Shape_group_file
00109   (
00110   const char *nm      // Basename.
00111   ) : name(nm), modified(false)
00112   {
00113   Flex *flex = 0;
00114   std::string patchname = "<PATCH>/" + name;
00115   std::string staticname = "<STATIC>/" + name;
00116   if (U7exists(patchname))  // First try 'patch' directory.
00117     flex = new Flex(patchname);
00118   else if (U7exists(staticname))
00119     flex = new Flex(staticname);
00120   if (flex)     // Exists?
00121     {
00122     int cnt = flex->number_of_objects();
00123     for (int i = 0; i < cnt; i++)
00124       {   // Get each group.
00125       std::size_t len;
00126       char *buf = flex->retrieve(i, len);
00127       char *gname = buf;  // Starts with name.
00128       unsigned char *ptr = (unsigned char *)
00129             gname + strlen(gname) + 1;
00130       int sz = Read2(ptr);  // Get # entries.
00131       assert ((len - ((char *) ptr - buf))/2 == sz);
00132       Shape_group *grp = new Shape_group(gname, this);
00133       grp->reserve(sz);
00134       for (int j = 0; j < sz; j++)
00135         grp->push_back(Read2(ptr));
00136       groups.push_back(grp);
00137       delete buf;
00138       }
00139     delete flex;
00140     }
00141   }
00142 
00143 /*
00144  *  Search for a group with a given name.
00145  *
00146  *  Output: Index if found, else -1.
00147  */
00148 
00149 int Shape_group_file::find
00150   (
00151   const char *nm
00152   )
00153   {
00154   for (vector<Shape_group *>::const_iterator it = groups.begin();
00155             it != groups.end(); ++it)
00156     if ((*it)->name == nm)
00157       return (it - groups.begin());
00158   return -1;
00159   }
00160 
00161 /*
00162  *  Clean up.
00163  */
00164 
00165 Shape_group_file::~Shape_group_file
00166   (
00167   )
00168   {
00169   for (vector<Shape_group *>::iterator it = groups.begin();
00170             it != groups.end(); ++it)
00171     delete (*it);   // Delete each group.
00172   }
00173 
00174 /*
00175  *  Remove and delete a group.
00176  */
00177 
00178 void Shape_group_file::remove
00179   (
00180   int index,
00181   bool del      // True to delete the group.
00182   )
00183   {
00184   modified = true;
00185   assert(index >= 0 && index < groups.size());
00186   Shape_group *grp = groups[index];
00187   groups.erase(groups.begin() + index);
00188   if (del)
00189     delete grp;
00190   }
00191 
00192 /*
00193  *  Write out to the 'patch' directory.
00194  */
00195 
00196 void Shape_group_file::write
00197   (
00198   )
00199   {
00200   std::ofstream out;
00201   std::string patchname = "<PATCH>/" + name;
00202   U7open(out, patchname.c_str());
00203   int cnt = groups.size();  // # groups.
00204   Flex_writer gfile(out, "ExultStudio shape groups", cnt);
00205   int i;        // Write each group.
00206   for (i = 0; i < cnt; i++)
00207     {
00208     Shape_group *grp = groups[i];
00209     const char *nm = grp->get_name();
00210     int sz = grp->size();
00211           // Name, #entries, entries(2-bytes).
00212     long len = strlen(nm) + 1 + 2 + 2*sz;
00213     unsigned char *buf = new unsigned char[len];
00214     strcpy((char *) buf, nm);
00215     unsigned char *ptr = buf + strlen(nm) + 1;
00216     Write2(ptr, sz);  // # entries.
00217     for (vector<int>::iterator it = grp->begin();
00218             it != grp->end(); it++)
00219       Write2(ptr, *it);
00220     assert(ptr - buf == len);
00221           // Write out to file.
00222     out.write(reinterpret_cast<char *>(buf), len);
00223     delete buf;
00224     gfile.mark_section_done();
00225     }
00226   if (!gfile.close())
00227     Alert("Error writing '%s'", patchname.c_str());
00228   modified = false;
00229   }
00230 
00231 /*
00232  *  Get the tree row # (assuming just a simple list) for a given tree-
00233  *  model position.
00234  */
00235 
00236 static int Get_tree_row
00237   (
00238   GtkTreePath *path
00239   )
00240   {
00241   gchar *str = gtk_tree_path_to_string(path);
00242   int row = atoi(str);
00243   g_free(str);
00244   return row;
00245   }
00246 static int Get_tree_row
00247   (
00248   GtkTreeModel *model,
00249   GtkTreeIter *iter   // Position we want.
00250   )
00251   {
00252   GtkTreePath *path = gtk_tree_model_get_path(model, iter);
00253   int row = Get_tree_row(path);
00254   gtk_tree_path_free(path);
00255   return row;
00256   }
00257 
00258 /*
00259  *  Group buttons:
00260  */
00261 C_EXPORT void
00262 on_groups_add_clicked     (GtkToggleButton *button,
00263            gpointer   user_data)
00264 {
00265   ExultStudio::get_instance()->add_group();
00266 }
00267 
00268 C_EXPORT void
00269 on_groups_del_clicked     (GtkToggleButton *button,
00270            gpointer   user_data)
00271 {
00272   ExultStudio::get_instance()->del_group();
00273 }
00274 
00275 C_EXPORT gboolean
00276 on_groups_new_name_key_press    (GtkEntry *entry,
00277            GdkEventKey  *event,
00278            gpointer  user_data)
00279 {
00280   if (event->keyval == GDK_Return)
00281     {
00282     ExultStudio::get_instance()->add_group();
00283     return TRUE;
00284     }
00285   return FALSE;     // Let parent handle it.
00286 }
00287 
00288 /*
00289  *  Groups list signals:
00290  */
00291 C_EXPORT void
00292 on_group_list_cursor_changed    (GtkTreeView  *tview)
00293 {
00294   ExultStudio::get_instance()->setup_group_controls();
00295 }
00296 
00297 void
00298 on_group_list_row_inserted    (GtkTreeModel *model,
00299            GtkTreePath *path,
00300            GtkTreeIter *iter,
00301            gpointer user_data)
00302 {
00303   ExultStudio::get_instance()->groups_changed(model, path, iter);
00304 }
00305 
00306 void
00307 on_group_list_row_changed   (GtkTreeModel *model,
00308            GtkTreePath *path,
00309            GtkTreeIter *iter,
00310            gpointer user_data)
00311 {
00312   ExultStudio::get_instance()->groups_changed(model, path, iter, true);
00313 }
00314 
00315 void
00316 on_group_list_row_deleted   (GtkTreeModel *model,
00317            GtkTreePath *path,
00318            gpointer user_data)
00319 {
00320   ExultStudio::get_instance()->groups_changed(model, path, 0);
00321 }
00322 
00323 C_EXPORT void
00324 on_group_list_row_activated   (GtkTreeView  *treeview,
00325            GtkTreePath  *path,
00326            GtkTreeViewColumn *column,
00327            gpointer  user_data)
00328 {
00329   ExultStudio::get_instance()->open_group_window();
00330 }
00331 
00332 /* columns */
00333 enum
00334 {
00335   GRP_FILE_COLUMN = 0,
00336   GRP_GROUP_COLUMN,
00337   GRP_NUM_COLUMNS
00338 };
00339 
00340 /*
00341  *  Initialize the list of shape groups for the file being shown in the
00342  *  browser.
00343  */
00344 
00345 void ExultStudio::setup_groups
00346   (
00347   )
00348   {
00349   Shape_group_file *groups = curfile->get_groups();
00350   if (!groups)      // No groups?
00351     {
00352     set_visible("groups_frame", FALSE);
00353     return;
00354     }
00355   GtkTreeView *tview = GTK_TREE_VIEW(
00356         glade_xml_get_widget(app_xml, "group_list"));
00357   GtkTreeModel *oldmod = gtk_tree_view_get_model(tview);
00358   GtkTreeStore *model;
00359   gulong addsig = 0, delsig = 0, chgsig = 0;
00360   if (!oldmod)      // Create model first time.
00361     {
00362       model = gtk_tree_store_new(GRP_NUM_COLUMNS, 
00363             G_TYPE_STRING, G_TYPE_POINTER);
00364     gtk_tree_view_set_model(tview, GTK_TREE_MODEL(model));
00365     g_object_unref(model);
00366           // Create column.
00367       GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
00368     g_object_set (renderer, "xalign", 0.0, NULL);
00369     gint col_offset = gtk_tree_view_insert_column_with_attributes(
00370         tview,
00371         -1, "Names",
00372         renderer, "text",
00373         GRP_FILE_COLUMN, NULL);
00374     GtkTreeViewColumn *column = gtk_tree_view_get_column(tview, 
00375               col_offset - 1);
00376     gtk_tree_view_column_set_clickable(column, TRUE);
00377     addsig = g_signal_connect(G_OBJECT(model), "row-inserted",
00378       GTK_SIGNAL_FUNC(on_group_list_row_inserted), this);
00379           // Store signal id with model.
00380     g_object_set_data(G_OBJECT(model), "row-inserted",
00381               (gpointer) addsig);
00382     delsig = g_signal_connect(G_OBJECT(model), "row-deleted",
00383       GTK_SIGNAL_FUNC(on_group_list_row_deleted), this);
00384     g_object_set_data(G_OBJECT(model), "row-deleted",
00385               (gpointer) delsig);
00386     chgsig = g_signal_connect(G_OBJECT(model), "row-changed",
00387       GTK_SIGNAL_FUNC(on_group_list_row_changed), this);
00388     g_object_set_data(G_OBJECT(model), "row-changed",
00389               (gpointer) delsig);
00390     }
00391   else
00392     {
00393     model = GTK_TREE_STORE(oldmod);
00394     addsig = (gulong) g_object_get_data(G_OBJECT(model), 
00395               "row-inserted");
00396     delsig = (gulong) g_object_get_data(G_OBJECT(model), 
00397               "row-deleted");
00398     chgsig = (gulong) g_object_get_data(G_OBJECT(model), 
00399               "row-changed");
00400     }
00401           // Block this signal during creation.
00402   g_signal_handler_block(model, addsig);
00403   g_signal_handler_block(model, delsig);
00404   g_signal_handler_block(model, chgsig);
00405   gtk_tree_store_clear(model);
00406   set_visible("groups_frame", TRUE);
00407   gtk_tree_view_set_reorderable(tview, TRUE);
00408   int cnt = groups->size(); // Add groups from file.
00409   GtkTreeIter iter;
00410   for (int i = 0; i < cnt; i++)
00411     {
00412     Shape_group *grp = groups->get(i);
00413     gtk_tree_store_append(model, &iter, NULL);
00414     gtk_tree_store_set(model, &iter,
00415       GRP_FILE_COLUMN, grp->get_name(),
00416       GRP_GROUP_COLUMN, grp,
00417       -1);
00418     }
00419   gtk_tree_view_set_rules_hint(tview, TRUE);
00420   g_signal_handler_unblock(model, addsig);
00421   g_signal_handler_unblock(model, delsig);
00422   g_signal_handler_unblock(model, chgsig);
00423   setup_group_controls();   // Enable/disable the controls.
00424   }
00425 
00426 /*
00427  *  Enable/disable the controls based on whether there's a selection.
00428  */
00429 
00430 void ExultStudio::setup_group_controls
00431   (
00432   )
00433   {
00434   set_visible("groups_frame", true);
00435   GtkTreeView *tview = GTK_TREE_VIEW(
00436         glade_xml_get_widget(app_xml, "group_list"));
00437   GtkTreeSelection *list = gtk_tree_view_get_selection(tview);
00438   if (list)
00439     {
00440 //    int row = (int) list->data;
00441 //    set_sensitive("groups_open", true);
00442     set_sensitive("groups_del", true);
00443 //    set_sensitive("groups_up_arrow", row > 0);
00444 //    set_sensitive("groups_down_arrow", row < clist->rows);
00445     }
00446   else
00447     {
00448 //    set_sensitive("groups_open", false);
00449     set_sensitive("groups_del", false);
00450 //    set_sensitive("groups_up_arrow", false);
00451 //    set_sensitive("groups_down_arrow", false);
00452     }
00453   }
00454 
00455 /*
00456  *  Add/delete a new group.
00457  */
00458 
00459 void ExultStudio::add_group
00460   (
00461   )
00462   {
00463   if (!curfile)
00464     return;
00465   GtkTreeView *tview = GTK_TREE_VIEW(
00466         glade_xml_get_widget(app_xml, "group_list"));
00467     GtkTreeStore *model = GTK_TREE_STORE(gtk_tree_view_get_model(tview));
00468   const char *nm = get_text_entry("groups_new_name");
00469   Shape_group_file *groups = curfile->get_groups();
00470           // Make sure name isn't already there.
00471   if (nm && *nm && groups->find(nm) < 0)
00472     {
00473     Shape_group *grp = new Shape_group(nm, groups);
00474     GtkTreeIter iter;
00475     gtk_tree_store_append(model, &iter, NULL);
00476     gtk_tree_store_set(model, &iter,
00477       GRP_FILE_COLUMN, nm,
00478       GRP_GROUP_COLUMN, grp,
00479       -1);
00480     }
00481   set_entry("groups_new_name", "");
00482   }
00483 
00484 void ExultStudio::del_group
00485   (
00486   )
00487   {
00488   if (!curfile)
00489     return;
00490   GtkTreeView *tview = GTK_TREE_VIEW(
00491         glade_xml_get_widget(app_xml, "group_list"));
00492   GtkTreeSelection *list = gtk_tree_view_get_selection(tview);
00493   if (!list)
00494     return;
00495   GtkTreeModel *model;
00496   GtkTreeIter iter;
00497   if (!gtk_tree_selection_get_selected(list, &model, &iter))
00498     return;
00499   int row = Get_tree_row(model, &iter);
00500   Shape_group_file *groups = curfile->get_groups();
00501   Shape_group *grp = groups->get(row);
00502   string msg("Delete group '");
00503   msg += grp->get_name();
00504   msg += "'?";
00505   int choice = prompt(msg.c_str(), "Yes", "No");
00506   if (choice != 0)    // Yes?
00507     return;
00508   delete groups->get(row);  // Delete the group.
00509   gtk_tree_store_remove(GTK_TREE_STORE(model), &iter);
00510           // Close the group's windows.
00511   vector<GtkWindow*> toclose;
00512   vector<GtkWindow*>::const_iterator it;
00513   for (it = group_windows.begin(); it != group_windows.end(); ++it)
00514     {
00515     Object_browser *chooser = (Object_browser *) 
00516       gtk_object_get_data(GTK_OBJECT(*it), "browser");
00517     if (chooser->get_group() == grp)
00518           // A match?
00519       toclose.push_back(*it);
00520     }
00521   for (it = toclose.begin(); it != toclose.end(); ++it)
00522     close_group_window(GTK_WIDGET(*it));
00523   }
00524 
00525 /*
00526  *  A group has been inserted or deleted from the list.
00527  */
00528 
00529 void ExultStudio::groups_changed
00530   (
00531   GtkTreeModel *model,
00532   GtkTreePath *path,    // Position.
00533   GtkTreeIter *loc,   // Insert/change location, or 0.
00534   bool value      // True if value changed at loc.
00535   )
00536   {
00537   if (!curfile)
00538     return;
00539   Shape_group_file *groups = curfile->get_groups();
00540   int row = Get_tree_row(path);
00541   if (!loc)
00542     groups->remove(row, false);
00543   else
00544     {
00545     void *grpaddr = 0;
00546     gtk_tree_model_get(model, loc, GRP_GROUP_COLUMN, &grpaddr,
00547                 -1);
00548     Shape_group *grp = (Shape_group *) grpaddr;
00549     if (value)    // Changed?
00550       groups->set(grp, row);
00551     else
00552       groups->insert(grp, row);
00553     }
00554   }
00555 
00556 /*
00557  *  Events on 'group' window:
00558  */
00559 /*
00560  *  Npc window's close button.
00561  */
00562 C_EXPORT gboolean on_group_window_delete_event
00563   (
00564   GtkWidget *widget,
00565   GdkEvent *event,
00566   gpointer user_data
00567   )
00568   {
00569   ExultStudio::get_instance()->close_group_window(widget);
00570   return TRUE;
00571   }
00572 C_EXPORT void
00573 on_group_up_clicked     (GtkToggleButton *button,
00574            gpointer   user_data)
00575 {
00576   Object_browser *chooser = (Object_browser *)gtk_object_get_data(
00577     GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))), 
00578               "browser");
00579   Shape_group *grp = chooser->get_group();
00580   int i = chooser->get_selected();
00581   if (grp && i > 0)   // Moving item up.
00582     {
00583     grp->swap(i - 1);
00584     ExultStudio::get_instance()->update_group_windows(grp);
00585     }
00586 }
00587 C_EXPORT void
00588 on_group_down_clicked     (GtkToggleButton *button,
00589            gpointer   user_data)
00590 {
00591   Object_browser *chooser = (Object_browser *)gtk_object_get_data(
00592     GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))), 
00593               "browser");
00594   Shape_group *grp = chooser->get_group();
00595   int i = chooser->get_selected();
00596   if (grp && i < grp->size() - 1) // Moving down.
00597     {
00598     grp->swap(i);
00599     ExultStudio::get_instance()->update_group_windows(grp);
00600     }
00601 }
00602 C_EXPORT void
00603 on_group_shape_remove_clicked   (GtkToggleButton *button,
00604            gpointer   user_data)
00605 {
00606   Object_browser *chooser = (Object_browser *)gtk_object_get_data(
00607     GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))), 
00608               "browser");
00609   Shape_group *grp = chooser->get_group();
00610   int i = chooser->get_selected();
00611   if (grp && i >= 0)
00612     {
00613     grp->del(i);
00614     ExultStudio::get_instance()->update_group_windows(grp);
00615     }
00616 }
00617 
00618 /*
00619  *  Open a 'group' window for the currently selected group.
00620  */
00621 
00622 void ExultStudio::open_group_window
00623   (
00624   )
00625   {
00626   GtkTreeView *tview = GTK_TREE_VIEW(
00627         glade_xml_get_widget(app_xml, "group_list"));
00628   GtkTreeSelection *list = gtk_tree_view_get_selection(tview);
00629   if (!list || !curfile || !vgafile || !palbuf)
00630     return;
00631   GtkTreeModel *model;
00632   GtkTreeIter iter;
00633   if (!gtk_tree_selection_get_selected(list, &model, &iter))
00634     return;
00635   int row = Get_tree_row(model, &iter);
00636   Shape_group_file *groups = curfile->get_groups();
00637   Shape_group *grp = groups->get(row);
00638   GladeXML *xml = glade_xml_new(glade_path, "group_window", NULL);
00639   glade_xml_signal_autoconnect(xml);
00640   GtkWidget *grpwin = glade_xml_get_widget(xml, "group_window");
00641   Object_browser *chooser = curfile->create_browser(vgafile,palbuf, grp);
00642           // Set xml as data on window.
00643   gtk_object_set_data(GTK_OBJECT(grpwin), "xml", xml);
00644   gtk_object_set_data(GTK_OBJECT(grpwin), "browser", chooser);
00645           // Set window title, name field.
00646   string title("Exult Group:  ");
00647   title += grp->get_name();
00648   gtk_window_set_title(GTK_WINDOW(grpwin), title.c_str());
00649   GtkWidget *field = glade_xml_get_widget(xml, "group_name");
00650   if (field)
00651     gtk_entry_set_text(GTK_ENTRY(field), grp->get_name());
00652           // Attach browser.
00653   GtkWidget *browser_box = glade_xml_get_widget(xml, "group_shapes" );
00654   gtk_widget_show(browser_box);
00655   gtk_box_pack_start(GTK_BOX(browser_box), chooser->get_widget(), 
00656                 TRUE, TRUE, 0);
00657           // Auto-connect doesn't seem to work.
00658   gtk_signal_connect (GTK_OBJECT(grpwin), "delete_event",
00659                       GTK_SIGNAL_FUNC (on_group_window_delete_event),
00660                       this);
00661   group_windows.push_back(GTK_WINDOW(grpwin));
00662   gtk_widget_show(grpwin);
00663   }
00664 
00665 /*
00666  *  Close a 'group' window.
00667  */
00668 
00669 void ExultStudio::close_group_window
00670   (
00671   GtkWidget *grpwin
00672   )
00673   {
00674           // Remove from list.
00675   for (vector<GtkWindow*>::iterator it = group_windows.begin();
00676           it != group_windows.end(); ++it)
00677     {
00678     if (*it == GTK_WINDOW(grpwin))
00679       {
00680       group_windows.erase(it);
00681       break;
00682       }
00683     }
00684   GladeXML *xml = (GladeXML *) gtk_object_get_data(GTK_OBJECT(grpwin), 
00685               "xml");
00686   Object_browser *chooser = (Object_browser *) gtk_object_get_data(
00687       GTK_OBJECT(grpwin), "browser");
00688   delete chooser;
00689   gtk_widget_destroy(grpwin);
00690   g_object_unref(G_OBJECT(xml));
00691   }
00692 
00693 /*
00694  *  Save all modified group files.
00695  */
00696 
00697 void ExultStudio::save_groups
00698   (
00699   )
00700   {
00701   if (!files)
00702     return;
00703   int cnt = files->size();
00704   for (int i = 0; i < cnt; i++) // Check each file.
00705     {
00706     Shape_file_info *info = (*files)[i];
00707     Shape_group_file *gfile = info->get_groups();
00708     if (gfile && gfile->is_modified())
00709       gfile->write();
00710     }
00711   }
00712 
00713 /*
00714  *  Return TRUE if any groups have been modified.
00715  */
00716 
00717 bool ExultStudio::groups_modified
00718   (
00719   )
00720   {
00721   if (!files)
00722     return false;
00723   int cnt = files->size();
00724   for (int i = 0; i < cnt; i++) // Check each file.
00725     {
00726     Shape_file_info *info = (*files)[i];
00727     Shape_group_file *gfile = info->get_groups();
00728     if (gfile && gfile->is_modified())
00729       return true;
00730     }
00731   return false;
00732   }
00733 
00734 /*
00735  *  Update all windows showing a given group.
00736  */
00737 
00738 void ExultStudio::update_group_windows
00739   (
00740   Shape_group *grp    // Group, or 0 for all.
00741   )
00742   {
00743   for (vector<GtkWindow*>::const_iterator it = group_windows.begin();
00744           it != group_windows.end(); ++it)
00745     {
00746     Object_browser *chooser = (Object_browser *) 
00747       gtk_object_get_data(GTK_OBJECT(*it), "browser");
00748     if (!grp || chooser->get_group() == grp)
00749       {   // A match?
00750       chooser->render();
00751       chooser->show();
00752       }
00753     }
00754   }
00755 

Generated on Mon Jul 9 14:42:48 2007 for ExultEngine by  doxygen 1.5.1