00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028
00029 #include <gdk/gdkkeysyms.h>
00030 #include "studio.h"
00031 #include "combo.h"
00032 #include "exult_constants.h"
00033 #include "exceptions.h"
00034 #include "shapevga.h"
00035 #include "shapefile.h"
00036 #include "ibuf8.h"
00037 #include "objserial.h"
00038 #include "shapegroup.h"
00039 #include "Flex.h"
00040 #include "u7drag.h"
00041
00042 using std::cout;
00043 using std::cin;
00044 using std::endl;
00045
00046 const int border = 2;
00047
00048 const int maxtiles = 32;
00049
00050
00051
00052
00053
00054 C_EXPORT void on_new_combo1_activate
00055 (
00056 GtkMenuItem *menuitem,
00057 gpointer user_data
00058 )
00059 {
00060 ExultStudio *studio = ExultStudio::get_instance();
00061 studio->open_combo_window();
00062 }
00063 void ExultStudio::open_combo_window
00064 (
00065 )
00066 {
00067 if (combowin && combowin->is_visible())
00068 return;
00069 if (!vgafile)
00070 {
00071 EStudio::Alert("'shapes.vga' file isn't present");
00072 return;
00073 }
00074 Shapes_vga_file *svga = (Shapes_vga_file *) vgafile->get_ifile();
00075 delete combowin;
00076 combowin = new Combo_editor(svga, palbuf);
00077 combowin->show(true);
00078
00079 GtkWidget *mitem = glade_xml_get_widget(app_xml, "pick_for_combo1");
00080 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(mitem), TRUE);
00081 }
00082
00083
00084
00085
00086
00087 void ExultStudio::save_combos
00088 (
00089 )
00090 {
00091
00092 Shape_file_info *combos = files->create("combos.flx");
00093 try {
00094 if (combos)
00095 combos->flush();
00096 } catch (const exult_exception& e) {
00097 EStudio::Alert(e.what());
00098 }
00099 }
00100
00101
00102
00103
00104 C_EXPORT gint on_combo_draw_expose_event
00105 (
00106 GtkWidget *widget,
00107 GdkEventExpose *event,
00108 gpointer data
00109 )
00110 {
00111 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00112 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget))));
00113 combo->render(&event->area);
00114 return TRUE;
00115 }
00116
00117 C_EXPORT void
00118 on_combo_remove_clicked (GtkButton *button,
00119 gpointer user_data)
00120 {
00121 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00122 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))));
00123 combo->remove();
00124 }
00125
00126 C_EXPORT void
00127 on_combo_apply_clicked (GtkButton *button,
00128 gpointer user_data)
00129 {
00130 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00131 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))));
00132 combo->save();
00133 }
00134
00135 C_EXPORT void
00136 on_combo_ok_clicked (GtkButton *button,
00137 gpointer user_data)
00138 {
00139 GtkWidget *win = gtk_widget_get_toplevel(GTK_WIDGET(button));
00140 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00141 GTK_OBJECT(win));
00142 combo->save();
00143 gtk_widget_hide(win);
00144 }
00145
00146 C_EXPORT void
00147 on_combo_locx_changed (GtkSpinButton *button,
00148 gpointer user_data)
00149 {
00150 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00151 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))));
00152 combo->set_position();
00153 }
00154
00155 C_EXPORT void
00156 on_combo_locy_changed (GtkSpinButton *button,
00157 gpointer user_data)
00158 {
00159 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00160 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))));
00161 combo->set_position();
00162 }
00163
00164 C_EXPORT void
00165 on_combo_locz_changed (GtkSpinButton *button,
00166 gpointer user_data)
00167 {
00168 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00169 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))));
00170 combo->set_position();
00171 }
00172
00173 C_EXPORT void
00174 on_combo_order_changed (GtkSpinButton *button,
00175 gpointer user_data)
00176 {
00177 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00178 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(button))));
00179 combo->set_order();
00180 }
00181
00182
00183
00184
00185 C_EXPORT gint on_combo_draw_button_press_event
00186 (
00187 GtkWidget *widget,
00188 GdkEventButton *event,
00189 gpointer data
00190 )
00191 {
00192 Combo_editor *combo = (Combo_editor *) gtk_object_get_user_data(
00193 GTK_OBJECT(gtk_widget_get_toplevel(GTK_WIDGET(widget))));
00194 return combo->mouse_press(event);
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204 int hot_spot_compare
00205 (
00206 Combo_member& c0,
00207 Combo_member& c1
00208 )
00209 {
00210 if (c0.tz < c1.tz)
00211 return 0;
00212 else if (c1.tz < c0.tz)
00213 return 1;
00214 else if (c0.ty > c1.ty)
00215 return 0;
00216 else if (c1.ty > c0.ty)
00217 return 1;
00218 else
00219 return c0.tx >= c1.tx ? 0 : 1;
00220 }
00221
00222
00223
00224
00225
00226 Rectangle Combo::get_member_footprint
00227 (
00228 int i
00229 )
00230 {
00231 Combo_member *m = members[i];
00232
00233 Shape_info& info = shapes_file->get_info(m->shapenum);
00234 int xtiles = info.get_3d_xtiles(m->framenum),
00235 ytiles = info.get_3d_ytiles(m->framenum);
00236
00237 Rectangle box(m->tx - xtiles + 1, m->ty - ytiles + 1,
00238 xtiles, ytiles);
00239 return box;
00240 }
00241
00242
00243
00244
00245
00246 Combo::Combo
00247 (
00248 Shapes_vga_file *svga
00249 ) : shapes_file(svga),
00250 starttx(c_num_tiles), startty(c_num_tiles), hot_index(-1),
00251 tilefoot(0, 0, 0, 0)
00252 {
00253
00254 shapes_file->read_info(false, true);
00255 }
00256
00257
00258
00259
00260
00261 Combo::Combo
00262 (
00263 const Combo& c2
00264 ) : shapes_file(c2.shapes_file), starttx(c2.starttx),
00265 startty(c2.startty),
00266 hot_index(c2.hot_index), name(c2.name), tilefoot(c2.tilefoot)
00267 {
00268 for (std::vector<Combo_member *>::const_iterator it = c2.members.begin();
00269 it != c2.members.end(); ++it)
00270 {
00271 Combo_member *m = *it;
00272 members.push_back(new Combo_member(m->tx, m->ty, m->tz,
00273 m->shapenum, m->framenum));
00274 }
00275 }
00276
00277
00278
00279
00280
00281 Combo::~Combo
00282 (
00283 )
00284 {
00285 for (std::vector<Combo_member *>::iterator it = members.begin();
00286 it != members.end(); ++it)
00287 delete *it;
00288 }
00289
00290
00291
00292
00293
00294 void Combo::add
00295 (
00296 int tx, int ty, int tz,
00297 int shnum, int frnum
00298 )
00299 {
00300
00301 for (std::vector<Combo_member *>::iterator it = members.begin();
00302 it != members.end(); ++it)
00303 {
00304 Combo_member *m = *it;
00305 if (tx == m->tx && ty == m->ty && tz == m->tz &&
00306 shnum == m->shapenum && frnum == m->framenum)
00307 return;
00308 }
00309
00310 Shape_info& info = shapes_file->get_info(shnum);
00311 int xtiles = info.get_3d_xtiles(frnum),
00312 ytiles = info.get_3d_ytiles(frnum),
00313 ztiles = info.get_3d_height();
00314
00315 Rectangle box(tx - xtiles + 1, ty - ytiles + 1, xtiles, ytiles);
00316 if (!members.size())
00317 tilefoot = box;
00318 else
00319 {
00320 if (tilefoot.x + tilefoot.w - box.x > maxtiles ||
00321 box.x + box.w - tilefoot.x > maxtiles ||
00322 tilefoot.y + tilefoot.h - box.y > maxtiles ||
00323 box.y + box.h - tilefoot.y > maxtiles)
00324 {
00325 EStudio::Alert(
00326 "New object is too far (> 32) from others");
00327 return;
00328 }
00329
00330 tilefoot = tilefoot.add(box);
00331 }
00332 Combo_member *memb = new Combo_member(tx, ty, tz, shnum, frnum);
00333 members.push_back(memb);
00334
00335
00336 int vtx = tx - xtiles - 2 - (tz + ztiles + 1)/2,
00337 vty = ty - ytiles - 2 - (tz + ztiles + 1)/2;
00338 if (vtx < starttx)
00339 starttx = vtx;
00340 if (vty < startty)
00341 startty = vty;
00342 if (hot_index == -1 ||
00343 hot_spot_compare(*memb, *members[hot_index]) == 0)
00344 hot_index = members.size() - 1;
00345 }
00346
00347
00348
00349
00350
00351 void Combo::remove
00352 (
00353 int i
00354 )
00355 {
00356 if (i < 0 || i >= members.size())
00357 return;
00358
00359 std::vector<Combo_member *>::iterator it = members.begin() + i;
00360 Combo_member *m = *it;
00361 members.erase(it);
00362 delete m;
00363 hot_index = -1;
00364 tilefoot = Rectangle(0, 0, 0, 0);
00365 for (std::vector<Combo_member *>::iterator it = members.begin();
00366 it != members.end(); ++it)
00367 {
00368 Combo_member *m = *it;
00369 int index = it - members.begin();
00370 Rectangle box = get_member_footprint(index);
00371 if (hot_index == -1)
00372 {
00373 hot_index = 0;
00374 tilefoot = box;
00375 }
00376 else
00377 {
00378 if (hot_spot_compare(*m, *members[hot_index]) == 0)
00379 hot_index = index;
00380 tilefoot = tilefoot.add(box);
00381 }
00382 }
00383 }
00384
00385
00386
00387
00388
00389 void Combo::draw
00390 (
00391 Shape_draw *draw,
00392 int selected,
00393 int xoff, int yoff
00394 )
00395 {
00396 int selx = -1000, sely = -1000;
00397 bool selfound = false;
00398 for (std::vector<Combo_member *>::iterator it = members.begin();
00399 it != members.end(); ++it)
00400 {
00401 Combo_member *m = *it;
00402
00403 int lft = m->tz*(c_tilesize/2);
00404
00405 int mtx = m->tx - starttx,
00406 mty = m->ty - startty;
00407
00408 int x = mtx*c_tilesize - lft,
00409 y = mty*c_tilesize - lft;
00410 Shape_frame *shape = shapes_file->get_shape(m->shapenum,
00411 m->framenum);
00412 if (!shape)
00413 continue;
00414
00415 x -= shape->get_xleft();
00416 y -= shape->get_yabove();
00417 x += xoff; y += yoff;
00418 draw->draw_shape(shape, x, y);
00419 if (it - members.begin() == selected)
00420 {
00421 selx = x;
00422 sely = y;
00423 selfound = true;
00424 }
00425 }
00426 if (selfound)
00427 {
00428 Combo_member *m = members[selected];
00429
00430 draw->draw_shape_outline(m->shapenum, m->framenum,
00431 selx, sely, 1);
00432 }
00433 }
00434
00435
00436
00437
00438
00439
00440
00441 int Combo::find
00442 (
00443 int mx, int my
00444 )
00445 {
00446 int cnt = members.size();
00447 for (int i = cnt - 1; i >= 0; i--)
00448 {
00449 Combo_member *m = members[i];
00450
00451 int lft = m->tz*(c_tilesize/2);
00452
00453 int mtx = m->tx - starttx,
00454 mty = m->ty - startty;
00455 int x = mtx*c_tilesize - lft,
00456 y = mty*c_tilesize - lft;
00457 Shape_frame *frame = shapes_file->get_shape(
00458 m->shapenum, m->framenum);
00459 if (frame && frame->has_point(mx - x, my - y))
00460 return i;
00461 }
00462 return -1;
00463 }
00464
00465
00466
00467
00468
00469
00470
00471 unsigned char *Combo::write
00472 (
00473 int& datalen
00474
00475 )
00476 {
00477 int namelen = name.length();
00478
00479 unsigned char *buf = new unsigned char[namelen + 1 +
00480 7*4 + members.size()*(5*4)];
00481 unsigned char *ptr = buf;
00482 Serial_out out(ptr);
00483 out << name;
00484 out << hot_index << starttx << startty;
00485 out << (short) members.size();
00486 for (std::vector<Combo_member *>::const_iterator it = members.begin();
00487 it != members.end(); ++it)
00488 {
00489 Combo_member *m = *it;
00490 out << m->tx << m->ty << m->tz << m->shapenum <<
00491 m->framenum;
00492 }
00493 datalen = ptr - buf;
00494 return buf;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503 unsigned char *Combo::read
00504 (
00505 unsigned char *buf,
00506 int bufsize
00507 )
00508 {
00509 unsigned char *ptr = buf;
00510 Serial_in in(ptr);
00511 in << name;
00512 in << hot_index << starttx << startty;
00513 short cnt;
00514 in << cnt;
00515 for (int i = 0; i < cnt; i++)
00516 {
00517 short tx, ty, tz, shapenum, framenum;
00518 in << tx << ty << tz << shapenum << framenum;
00519 Combo_member *memb = new Combo_member(tx, ty, tz,
00520 shapenum, framenum);
00521 members.push_back(memb);
00522 Rectangle box = get_member_footprint(i);
00523 if (i == 0)
00524 tilefoot = box;
00525 else
00526 tilefoot = tilefoot.add(box);
00527 }
00528 return ptr;
00529 }
00530
00531
00532
00533
00534
00535 void Combo_editor::set_combo
00536 (
00537 Combo *newcombo,
00538 int findex
00539 )
00540 {
00541 delete combo;
00542 combo = newcombo;
00543 file_index = findex;
00544 selected = -1;
00545 ExultStudio::get_instance()->set_entry(
00546 "combo_name", combo->name.c_str(), true);
00547 set_controls();
00548 render();
00549 }
00550
00551
00552
00553
00554
00555 Combo_editor::Combo_editor
00556 (
00557 Shapes_vga_file *svga,
00558 unsigned char *palbuf
00559 ) : Shape_draw(svga, palbuf, glade_xml_get_widget(
00560 ExultStudio::get_instance()->get_xml(), "combo_draw")),
00561 selected(-1), setting_controls(false), file_index(-1)
00562 {
00563 static bool first = true;
00564 combo = new Combo(svga);
00565 GladeXML *app_xml = ExultStudio::get_instance()->get_xml();
00566 win = glade_xml_get_widget(app_xml, "combo_win");
00567 gtk_object_set_user_data(GTK_OBJECT(win), this);
00568 if (first)
00569 {
00570 gtk_widget_set_events(draw, GDK_EXPOSURE_MASK |
00571 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
00572 GDK_BUTTON1_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
00573 first = false;
00574 }
00575 set_controls();
00576 }
00577
00578
00579
00580
00581
00582 Combo_editor::~Combo_editor
00583 (
00584 )
00585 {
00586 delete combo;
00587 }
00588
00589
00590
00591
00592
00593 void Combo_editor::show
00594 (
00595 bool tf
00596 )
00597 {
00598 if (tf)
00599 gtk_widget_show(win);
00600 else
00601 gtk_widget_hide(win);
00602 }
00603
00604
00605
00606
00607
00608 void Combo_editor::render
00609 (
00610 GdkRectangle *area
00611 )
00612 {
00613 Shape_draw::configure();
00614
00615 int draww = draw->allocation.width,
00616 drawh = draw->allocation.height;
00617 GdkRectangle all;
00618 if (!area)
00619 {
00620 all.x = all.y = 0;
00621 all.width = draww;
00622 all.height = drawh;
00623 area = &all;
00624 }
00625 gdk_gc_set_clip_rectangle(drawgc, area);
00626 iwin->fill8(255);
00627 combo->draw(this, selected);
00628 Shape_draw::show(area->x, area->y, area->width, area->height);
00629 }
00630
00631
00632
00633
00634
00635 void Combo_editor::set_controls
00636 (
00637 )
00638 {
00639 setting_controls = true;
00640 ExultStudio *studio = ExultStudio::get_instance();
00641 Combo_member *m = combo->get(selected);
00642 if (!m)
00643 {
00644 studio->set_spin("combo_locx", 0, false);
00645 studio->set_spin("combo_locy", 0, false);
00646 studio->set_spin("combo_locz", 0, false);
00647 studio->set_spin("combo_order", 0, false);
00648 studio->set_sensitive("combo_remove", false);
00649 }
00650 else
00651 {
00652 int draww = draw->allocation.width,
00653 drawh = draw->allocation.height;
00654 studio->set_sensitive("combo_locx", true);
00655 studio->set_spin("combo_locx", m->tx - combo->starttx,
00656 0, draww/c_tilesize);
00657 studio->set_sensitive("combo_locy", true);
00658 studio->set_spin("combo_locy", m->ty - combo->startty,
00659 0, drawh/c_tilesize);
00660 studio->set_sensitive("combo_locz", true);
00661 studio->set_spin("combo_locz", m->tz, 0, 15);
00662 studio->set_sensitive("combo_order", true);
00663 studio->set_spin("combo_order", selected, 0,
00664 combo->members.size() - 1);
00665 studio->set_sensitive("combo_remove", true);
00666 }
00667 setting_controls = false;
00668 }
00669
00670
00671
00672
00673
00674 gint Combo_editor::mouse_press
00675 (
00676 GdkEventButton *event
00677 )
00678 {
00679 if (event->button != 1)
00680 return FALSE;
00681
00682 int mx = (int) event->x, my = (int) event->y;
00683 selected = combo->find(mx, my);
00684 set_controls();
00685 render();
00686 return TRUE;
00687 }
00688
00689
00690
00691
00692
00693 void Combo_editor::set_order
00694 (
00695 )
00696 {
00697 if (setting_controls || selected < 0)
00698 return;
00699 ExultStudio *studio = ExultStudio::get_instance();
00700 int newi = studio->get_spin("combo_order");
00701 if (selected == newi)
00702 return;
00703 int dir = newi > selected ? 1 : -1;
00704 while (newi != selected)
00705 {
00706 Combo_member *tmp = combo->members[selected + dir];
00707 combo->members[selected + dir] = combo->members[selected];
00708 combo->members[selected] = tmp;
00709 selected += dir;
00710 }
00711 render();
00712 }
00713
00714
00715
00716
00717
00718 void Combo_editor::set_position
00719 (
00720 )
00721 {
00722 Combo_member *m = combo->get(selected);
00723 if (!m || setting_controls)
00724 return;
00725 ExultStudio *studio = ExultStudio::get_instance();
00726 m->tx = combo->starttx + studio->get_spin("combo_locx");
00727 m->ty = combo->startty + studio->get_spin("combo_locy");
00728 m->tz = studio->get_spin("combo_locz");
00729 render();
00730 }
00731
00732
00733
00734
00735
00736 int Combo_chooser::get_count
00737 (
00738 )
00739 {
00740 return group ? group->size() : combos.size();
00741 }
00742
00743
00744
00745
00746
00747 void Combo_editor::add
00748 (
00749 unsigned char *data,
00750 int datalen
00751 )
00752 {
00753 unsigned long addr;
00754 int tx, ty, tz;
00755 int shape, frame, quality;
00756 std::string name;
00757 if (!Object_in(data, datalen, addr, tx, ty, tz, shape, frame,
00758 quality, name))
00759 {
00760 cout << "Error decoding object" << endl;
00761 return;
00762 }
00763 combo->add(tx, ty, tz, shape, frame);
00764 render();
00765 }
00766
00767
00768
00769
00770
00771 void Combo_editor::remove
00772 (
00773 )
00774 {
00775 if (selected >= 0)
00776 {
00777 combo->remove(selected);
00778 selected = -1;
00779 set_controls();
00780 render();
00781 }
00782 }
00783
00784
00785
00786
00787
00788 void Combo_editor::save
00789 (
00790 )
00791 {
00792 ExultStudio *studio = ExultStudio::get_instance();
00793
00794 combo->name = studio->get_text_entry("combo_name");
00795 Flex_file_info *flex_info = dynamic_cast<Flex_file_info *>
00796 (studio->get_files()->create("combos.flx"));
00797 if (!flex_info)
00798 {
00799 EStudio::Alert("Can't open 'combos.flx'");
00800 return;
00801 }
00802 flex_info->set_modified();
00803 int len;
00804 unsigned char *newbuf = combo->write(len);
00805
00806 flex_info->set(file_index == -1 ? flex_info->size() : file_index,
00807 (char *) newbuf, len);
00808 Combo_chooser *browser = dynamic_cast<Combo_chooser *>(
00809 studio->get_browser());
00810 if (browser)
00811 file_index = browser->add(new Combo(*combo), file_index);
00812 }
00813
00814
00815
00816
00817
00818 void Combo_chooser::show
00819 (
00820 int x, int y, int w, int h
00821 )
00822 {
00823 Shape_draw::show(draw->window, x, y, w, h);
00824 if (selected >= 0)
00825 {
00826 Rectangle b = info[selected].box;
00827
00828 gdk_draw_rectangle(draw->window, drawgc, FALSE,
00829 b.x, b.y, b.w, b.h);
00830 }
00831 }
00832
00833
00834
00835
00836
00837
00838 void Combo_chooser::select
00839 (
00840 int new_sel
00841 )
00842 {
00843 if (new_sel < 0 || new_sel >= info_cnt)
00844 return;
00845 selected = new_sel;
00846 enable_controls();
00847 int num = info[selected].num;
00848 Combo *combo = combos[num];
00849
00850
00851 char buf[150];
00852 g_snprintf(buf, sizeof(buf), "Combo %d", num);
00853 if (combo && !combo->name.empty())
00854 {
00855 int len = strlen(buf);
00856 g_snprintf(buf + len, sizeof(buf) - len,
00857 ": '%s'", combo->name.c_str());
00858 }
00859 gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf);
00860 }
00861
00862
00863
00864
00865
00866 void Combo_chooser::unselect
00867 (
00868 bool need_render
00869 )
00870 {
00871 if (selected >= 0)
00872 {
00873 selected = -1;
00874 if (need_render)
00875 {
00876 render();
00877 show();
00878 }
00879 if (sel_changed)
00880 (*sel_changed)();
00881 }
00882 enable_controls();
00883 char buf[150];
00884 if (info_cnt > 0)
00885 {
00886
00887 g_snprintf(buf, sizeof(buf), "Combos %d to %d",
00888 info[0].num, info[info_cnt - 1].num);
00889 gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel, buf);
00890 }
00891 else
00892 {
00893
00894 gtk_statusbar_push(GTK_STATUSBAR(sbar), sbar_sel,
00895 "No combos");
00896 }
00897 }
00898
00899
00900
00901
00902
00903 void Combo_chooser::load
00904 (
00905 )
00906 {
00907 int cnt = combos.size();
00908 for (int i = 0; i < cnt; i++)
00909 delete combos[i];
00910 int num_combos = flex_info->size();
00911
00912 Shape_file_info *svga_info =
00913 ExultStudio::get_instance()->get_vgafile();
00914 Shapes_vga_file *svga = svga_info ?
00915 (Shapes_vga_file *) svga_info->get_ifile() : 0;
00916 combos.resize(num_combos);
00917 if (!svga)
00918 num_combos = 0;
00919
00920 for (int i = 0; i < num_combos; i++)
00921 {
00922 size_t len;
00923 unsigned char *buf = (unsigned char *) flex_info->get(i, len);
00924 Combo *combo = new Combo(svga);
00925 combo->read(buf, len);
00926 combos[i] = combo;
00927 }
00928 }
00929
00930
00931
00932
00933
00934 void Combo_chooser::render
00935 (
00936 )
00937 {
00938
00939 int selcombo = -1, new_selected = -1;
00940 if (selected >= 0)
00941 selcombo = info[selected].num;
00942
00943
00944 delete [] info;
00945
00946 gint winw = draw->allocation.width, winh = draw->allocation.height;
00947
00948 info = new Combo_info[256];
00949 info_cnt = 0;
00950
00951 iwin->fill8(255);
00952 int index = index0;
00953
00954 const int combow = 128, comboh = 128;
00955 int total_cnt = get_count();
00956 int y = border;
00957
00958 while (index < total_cnt && y + comboh/2 + border <= winh)
00959 {
00960 int x = border;
00961 int cliph = y + comboh <= winh ? comboh : (winh - y);
00962 while (index < total_cnt && x + combow + border <= winw)
00963 {
00964 iwin->set_clip(x, y, combow, cliph);
00965 int combonum = group ? (*group)[index] : index;
00966 combos[combonum]->draw(this, -1, x, y);
00967 iwin->clear_clip();
00968
00969 info[info_cnt].set(combonum, x, y, combow, comboh);
00970 if (combonum == selcombo)
00971
00972 new_selected = info_cnt;
00973 info_cnt++;
00974 index++;
00975 x += combow + border;
00976 }
00977 y += comboh + border;
00978 }
00979 if (new_selected == -1)
00980 unselect(false);
00981 else
00982 select(new_selected);
00983 }
00984
00985
00986
00987
00988
00989 void Combo_chooser::scroll
00990 (
00991 int newindex
00992 )
00993 {
00994 int total = combos.size();
00995 if (index0 < newindex)
00996 index0 = newindex < total ? newindex : total;
00997 else if (index0 > newindex)
00998 index0 = newindex >= 0 ? newindex : 0;
00999 render();
01000 show();
01001 }
01002
01003
01004
01005
01006
01007 void Combo_chooser::scroll
01008 (
01009 bool upwards
01010 )
01011 {
01012 GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(vscroll));
01013 float delta = adj->step_increment;
01014 if (upwards)
01015 delta = -delta;
01016 adj->value += delta;
01017 gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed");
01018 scroll((gint) adj->value);
01019 }
01020
01021
01022
01023
01024
01025 void Combo_chooser::drag_data_get
01026 (
01027 GtkWidget *widget,
01028 GdkDragContext *context,
01029 GtkSelectionData *seldata,
01030 guint info,
01031 guint time,
01032 gpointer data
01033 )
01034 {
01035 cout << "In DRAG_DATA_GET" << endl;
01036 Combo_chooser *chooser = (Combo_chooser *) data;
01037 if (chooser->selected < 0 || info != U7_TARGET_COMBOID)
01038 return;
01039
01040 int num = chooser->info[chooser->selected].num;
01041 Combo *combo = chooser->combos[num];
01042
01043 int cnt = combo->members.size();
01044 int buflen = 5*4 + cnt*5*4;
01045 cout << "Buflen = " << buflen << endl;
01046 guchar *buf = new unsigned char[buflen];
01047 guchar *ptr = buf;
01048 U7_combo_data *ents = new U7_combo_data[cnt];
01049
01050 Combo_member *hot = combo->members[combo->hot_index];
01051 for (int i = 0; i < cnt; i++)
01052 {
01053 Combo_member *m = combo->members[i];
01054 ents[i].tx = m->tx - hot->tx;
01055 ents[i].ty = m->ty - hot->ty;
01056 ents[i].tz = m->tz - hot->tz;
01057 ents[i].shape = m->shapenum;
01058 ents[i].frame = m->framenum;
01059 }
01060 Rectangle foot = combo->tilefoot;
01061 int len = Store_u7_comboid(buf, foot.w, foot.h,
01062 foot.x + foot.w - 1 - hot->tx,
01063 foot.y + foot.h - 1 - hot->ty, cnt, ents);
01064 assert(len <= buflen);
01065 #ifdef WIN32
01066 windragdata *wdata = (windragdata *)seldata;
01067 wdata->assign(info, len, buf);
01068 #else
01069
01070 gtk_selection_owner_set(widget, gdk_atom_intern("XdndSelection", 0),
01071 time);
01072
01073 gtk_selection_data_set(seldata,
01074 gdk_atom_intern(U7_TARGET_COMBOID_NAME, 0),
01075 8, buf, len);
01076 #endif
01077 delete buf;
01078 delete [] ents;
01079 }
01080
01081
01082
01083
01084
01085 gint Combo_chooser::selection_clear
01086 (
01087 GtkWidget *widget,
01088 GdkEventSelection *event,
01089 gpointer data
01090 )
01091 {
01092
01093 cout << "SELECTION_CLEAR" << endl;
01094 return TRUE;
01095 }
01096
01097
01098
01099
01100
01101 gint Combo_chooser::drag_begin
01102 (
01103 GtkWidget *widget,
01104 GdkDragContext *context,
01105 gpointer data
01106 )
01107 {
01108 cout << "In DRAG_BEGIN" << endl;
01109 Combo_chooser *chooser = (Combo_chooser *) data;
01110 if (chooser->selected < 0)
01111 return FALSE;
01112
01113 int num = chooser->info[chooser->selected].num;
01114 Combo *combo = chooser->combos[num];
01115
01116 Combo_member *hot = combo->members[combo->hot_index];
01117 Shape_frame *shape = combo->shapes_file->get_shape(hot->shapenum,
01118 hot->framenum);
01119 if (shape)
01120 chooser->set_drag_icon(context, shape);
01121 return TRUE;
01122 }
01123
01124
01125
01126
01127
01128 void Combo_chooser::scrolled
01129 (
01130 GtkAdjustment *adj,
01131 gpointer data
01132 )
01133 {
01134 Combo_chooser *chooser = (Combo_chooser *) data;
01135 gint newindex = (gint) adj->value;
01136 chooser->scroll(newindex);
01137 }
01138
01139
01140
01141
01142
01143
01144
01145 static gboolean
01146 on_combo_key_press (GtkEntry *entry,
01147 GdkEventKey *event,
01148 gpointer user_data)
01149 {
01150 Combo_chooser *chooser = (Combo_chooser *) user_data;
01151 switch (event->keyval)
01152 {
01153 case GDK_Delete:
01154 chooser->remove();
01155 return TRUE;
01156 }
01157 return FALSE;
01158 }
01159
01160
01161
01162
01163
01164 void Combo_chooser::enable_controls
01165 (
01166 )
01167 {
01168 if (selected == -1)
01169 {
01170 if (!group)
01171 {
01172 gtk_widget_set_sensitive(move_down, false);
01173 gtk_widget_set_sensitive(move_up, false);
01174 }
01175 return;
01176 }
01177 if (!group)
01178 {
01179 gtk_widget_set_sensitive(move_down,
01180 info[selected].num < combos.size() - 1);
01181 gtk_widget_set_sensitive(move_up,
01182 info[selected].num > 0);
01183 }
01184 }
01185
01186 static gint Mouse_release(GtkWidget *, GdkEventButton *, gpointer);
01187
01188
01189
01190
01191
01192 Combo_chooser::Combo_chooser
01193 (
01194 Vga_file *i,
01195 Flex_file_info *flinfo,
01196 unsigned char *palbuf,
01197 int w, int h,
01198 Shape_group *g
01199 ) : Object_browser(g, flinfo),
01200 Shape_draw(i, palbuf, gtk_drawing_area_new()),
01201 flex_info(flinfo), index0(0),
01202 info(0), info_cnt(0), sel_changed(0)
01203 {
01204 load();
01205
01206 GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
01207 set_widget(vbox);
01208 gtk_widget_show(vbox);
01209
01210 GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
01211 gtk_widget_show(hbox);
01212 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
01213
01214
01215 GtkWidget *frame = gtk_frame_new(NULL);
01216 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
01217 gtk_widget_show(frame);
01218 gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
01219
01220
01221 gtk_widget_set_events(draw, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
01222 | GDK_BUTTON_RELEASE_MASK
01223 | GDK_POINTER_MOTION_HINT_MASK |
01224 GDK_BUTTON1_MOTION_MASK | GDK_KEY_PRESS_MASK);
01225
01226 gtk_signal_connect(GTK_OBJECT(draw), "configure_event",
01227 GTK_SIGNAL_FUNC(configure), this);
01228
01229 gtk_signal_connect(GTK_OBJECT(draw), "expose_event",
01230 GTK_SIGNAL_FUNC(expose), this);
01231
01232 gtk_signal_connect(GTK_OBJECT(draw), "key-press-event",
01233 GTK_SIGNAL_FUNC (on_combo_key_press),
01234 this);
01235 GTK_WIDGET_SET_FLAGS(draw, GTK_CAN_FOCUS);
01236
01237 gtk_signal_connect(GTK_OBJECT(draw), "button_press_event",
01238 GTK_SIGNAL_FUNC(mouse_press), this);
01239 gtk_signal_connect(GTK_OBJECT(draw), "button_release_event",
01240 GTK_SIGNAL_FUNC(Mouse_release), this);
01241
01242 gtk_signal_connect(GTK_OBJECT(draw), "drag_begin",
01243 GTK_SIGNAL_FUNC(drag_begin), this);
01244 #ifdef WIN32
01245
01246 gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event",
01247 GTK_SIGNAL_FUNC(win32_drag_motion), this);
01248 #else
01249 gtk_signal_connect(GTK_OBJECT(draw), "motion_notify_event",
01250 GTK_SIGNAL_FUNC(drag_motion), this);
01251 #endif
01252 gtk_signal_connect (GTK_OBJECT(draw), "drag_data_get",
01253 GTK_SIGNAL_FUNC(drag_data_get), this);
01254 gtk_signal_connect (GTK_OBJECT(draw), "selection_clear_event",
01255 GTK_SIGNAL_FUNC(selection_clear), this);
01256 gtk_container_add (GTK_CONTAINER (frame), draw);
01257 gtk_drawing_area_size(GTK_DRAWING_AREA(draw), w, h);
01258 gtk_widget_show(draw);
01259
01260 GtkObject *combo_adj = gtk_adjustment_new(0, 0,
01261 combos.size(), 1,
01262 4, 1.0);
01263 vscroll = gtk_vscrollbar_new(GTK_ADJUSTMENT(combo_adj));
01264
01265 gtk_range_set_update_policy(GTK_RANGE(vscroll),
01266 GTK_UPDATE_DELAYED);
01267 gtk_box_pack_start(GTK_BOX(hbox), vscroll, FALSE, TRUE, 0);
01268
01269 gtk_signal_connect(GTK_OBJECT(combo_adj), "value_changed",
01270 GTK_SIGNAL_FUNC(scrolled), this);
01271 gtk_widget_show(vscroll);
01272
01273 GtkWidget *hbox1 = gtk_hbox_new(FALSE, 0);
01274 gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 0);
01275 gtk_widget_show(hbox1);
01276
01277 sbar = gtk_statusbar_new();
01278 sbar_sel = gtk_statusbar_get_context_id(GTK_STATUSBAR(sbar),
01279 "selection");
01280 gtk_box_pack_start(GTK_BOX(hbox1), sbar, TRUE, TRUE, 0);
01281 gtk_widget_show(sbar);
01282
01283 gtk_box_pack_start(GTK_BOX(vbox),
01284 create_controls(find_controls|move_controls), FALSE, FALSE, 0);
01285 }
01286
01287
01288
01289
01290
01291 Combo_chooser::~Combo_chooser
01292 (
01293 )
01294 {
01295 gtk_widget_destroy(get_widget());
01296 delete [] info;
01297 int i;
01298 int cnt = combos.size();
01299 for (i = 0; i < cnt; i++)
01300 delete combos[i];
01301 }
01302
01303
01304
01305
01306
01307
01308
01309 int Combo_chooser::add
01310 (
01311 Combo *newcombo,
01312 int index
01313 )
01314 {
01315 if (index == -1)
01316 {
01317 combos.push_back(newcombo);
01318 index = combos.size() - 1;
01319 }
01320 else
01321 {
01322 assert(index >= 0 && index < combos.size());
01323 delete combos[index];
01324 combos[index] = newcombo;
01325 }
01326 GtkAdjustment *adj =
01327 gtk_range_get_adjustment(GTK_RANGE(vscroll));
01328 adj->upper = combos.size();
01329 gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed");
01330 render();
01331 show();
01332 return index;
01333 }
01334
01335
01336
01337
01338
01339 void Combo_chooser::remove
01340 (
01341 )
01342 {
01343 if (selected < 0)
01344 return;
01345 int tnum = info[selected].num;
01346 Combo_editor *combowin = ExultStudio::get_instance()->get_combowin();
01347 if (combowin && combowin->is_visible() && combowin->file_index == tnum)
01348 {
01349 EStudio::Alert("Can't remove the combo you're editing");
01350 return;
01351 }
01352 if (EStudio::Prompt("Okay to remove selected combo?", "Yes", "no")
01353 != 0)
01354 return;
01355 selected = -1;
01356 Combo *todel = combos[tnum];
01357 delete todel;
01358 combos.erase(combos.begin() + tnum);
01359 flex_info->set_modified();
01360 flex_info->remove(tnum);
01361 GtkAdjustment *adj =
01362 gtk_range_get_adjustment(GTK_RANGE(vscroll));
01363 adj->upper = combos.size();
01364 gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed");
01365 render();
01366 show();
01367 }
01368
01369
01370
01371
01372
01373 void Combo_chooser::edit
01374 (
01375 )
01376 {
01377 if (selected < 0)
01378 return;
01379 Combo_editor *combowin = ExultStudio::get_instance()->get_combowin();
01380 if (combowin && combowin->is_visible())
01381 {
01382 EStudio::Alert("You're already editing a combo");
01383 return;
01384 }
01385 int tnum = info[selected].num;
01386 ExultStudio *studio = ExultStudio::get_instance();
01387 studio->open_combo_window();
01388 Combo_editor *ed = studio->get_combowin();
01389 if (!ed || !ed->is_visible())
01390 return;
01391 ed->set_combo(new Combo(*(combos[tnum])), tnum);
01392 }
01393
01394
01395
01396
01397
01398 gint Combo_chooser::configure
01399 (
01400 GtkWidget *widget,
01401 GdkEventConfigure *event,
01402 gpointer data
01403 )
01404 {
01405 Combo_chooser *chooser = (Combo_chooser *) data;
01406 chooser->Shape_draw::configure();
01407 chooser->render();
01408
01409 int w = event->width, h = event->height;
01410 int per_row = (w - border)/(128 + border);
01411 int num_rows = (h - border)/(128 + border);
01412 int page_size = per_row*num_rows;
01413 GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(
01414 chooser->vscroll));
01415 adj->step_increment = per_row;
01416 adj->page_increment = page_size;
01417 adj->page_size = page_size;
01418 gtk_signal_emit_by_name(GTK_OBJECT(adj), "changed");
01419 #if 0
01420 if (chooser->group)
01421 chooser->enable_drop();
01422 #endif
01423 return (TRUE);
01424 }
01425
01426
01427
01428
01429
01430 gint Combo_chooser::expose
01431 (
01432 GtkWidget *widget,
01433 GdkEventExpose *event,
01434 gpointer data
01435 )
01436 {
01437 Combo_chooser *chooser = (Combo_chooser *) data;
01438 chooser->show(event->area.x, event->area.y, event->area.width,
01439 event->area.height);
01440 return (TRUE);
01441 }
01442
01443 #ifdef WIN32
01444
01445
01446
01447
01448 static bool win32_button = false;
01449
01450 gint Combo_chooser::win32_drag_motion
01451 (
01452 GtkWidget *widget,
01453 GdkEventMotion *event,
01454 gpointer data
01455 )
01456 {
01457 if (win32_button)
01458 {
01459 win32_button = false;
01460
01461
01462 windragdata wdata;
01463
01464
01465
01466 drag_data_get(NULL, NULL, (GtkSelectionData *) &wdata,
01467 U7_TARGET_COMBOID, 0, data);
01468
01469 POINT pnt;
01470 GetCursorPos(&pnt);
01471
01472 LPDROPSOURCE idsrc = (LPDROPSOURCE) new Windropsource(0,
01473 pnt.x, pnt.y);
01474 LPDATAOBJECT idobj = (LPDATAOBJECT) new Winstudioobj(wdata);
01475 DWORD dndout;
01476
01477 HRESULT res = DoDragDrop(idobj, idsrc, DROPEFFECT_COPY, &dndout);
01478 if (FAILED(res)) {
01479 g_warning ("Oops! Something is wrong with OLE2 DnD..");
01480 }
01481
01482 delete idsrc;
01483 idobj->Release();
01484 }
01485
01486 return true;
01487 };
01488
01489 #else
01490 gint Combo_chooser::drag_motion
01491 (
01492 GtkWidget *widget,
01493 GdkEventMotion *event,
01494 gpointer data
01495 )
01496 {
01497 Combo_chooser *chooser = (Combo_chooser *) data;
01498 if (!chooser->dragging && chooser->selected >= 0)
01499 chooser->start_drag(U7_TARGET_COMBOID_NAME,
01500 U7_TARGET_COMBOID, (GdkEvent *) event);
01501 return true;
01502 }
01503 #endif
01504
01505
01506
01507
01508
01509 gint Combo_chooser::mouse_press
01510 (
01511 GtkWidget *widget,
01512 GdkEventButton *event,
01513 gpointer data
01514 )
01515 {
01516 gtk_widget_grab_focus(widget);
01517 Combo_chooser *chooser = (Combo_chooser *) data;
01518
01519 if (event->button == 4) {
01520 chooser->scroll(true);
01521 return(TRUE);
01522 } else if (event->button == 5) {
01523 chooser->scroll(false);
01524 return(TRUE);
01525 }
01526
01527
01528
01529 int old_selected = chooser->selected;
01530 int i;
01531 for (i = 0; i < chooser->info_cnt; i++)
01532 if (chooser->info[i].box.has_point(
01533 (int) event->x, (int) event->y))
01534 {
01535
01536 #ifdef WIN32
01537
01538
01539
01540
01541
01542 win32_button = true;
01543 #endif
01544 chooser->selected = i;
01545 chooser->render();
01546 chooser->show();
01547
01548 if (chooser->sel_changed)
01549 (*chooser->sel_changed)();
01550 break;
01551 }
01552 if (i == chooser->info_cnt && event->button == 1)
01553 chooser->unselect(true);
01554 else if (chooser->selected == old_selected && old_selected >= 0)
01555 {
01556 if (((GdkEvent *) event)->type == GDK_2BUTTON_PRESS)
01557 chooser->edit();
01558 }
01559 if (event->button == 3)
01560 gtk_menu_popup(GTK_MENU(chooser->create_popup()),
01561 0, 0, 0, 0, event->button, event->time);
01562 return (TRUE);
01563 }
01564
01565
01566
01567
01568 static gint Mouse_release
01569 (
01570 GtkWidget *widget,
01571 GdkEventButton *event,
01572 gpointer data
01573 )
01574 {
01575 Combo_chooser *chooser = (Combo_chooser *) data;
01576 chooser->mouse_up();
01577 }
01578
01579
01580
01581
01582
01583 void Combo_chooser::move
01584 (
01585 bool upwards
01586 )
01587 {
01588 if (selected < 0)
01589 return;
01590 int tnum = info[selected].num;
01591 if ((tnum == 0 && upwards) || (tnum == combos.size() - 1 && !upwards))
01592 return;
01593 if (upwards)
01594 tnum--;
01595 Combo *tmp = combos[tnum];
01596 combos[tnum] = combos[tnum + 1];
01597 combos[tnum + 1] = tmp;
01598 selected += upwards ? -1 : 1;
01599
01600 Combo_editor *combowin = ExultStudio::get_instance()->get_combowin();
01601 if (combowin && combowin->is_visible())
01602 {
01603 if (combowin->file_index == tnum)
01604 combowin->file_index = tnum + 1;
01605 else if (combowin->file_index == tnum + 1)
01606 combowin->file_index = tnum;
01607 }
01608 flex_info->set_modified();
01609 flex_info->swap(tnum);
01610 render();
01611 show();
01612 }
01613
01614
01615
01616
01617
01618 void Combo_chooser::search
01619 (
01620 const char *srch,
01621 int dir
01622 )
01623 {
01624 int total = get_count();
01625 if (!total)
01626 return;
01627 ExultStudio *studio = ExultStudio::get_instance();
01628
01629 int start = selected >= 0 ? info[selected].num : 0;
01630 int i;
01631 start += dir;
01632 int stop = dir == -1 ? -1 : total;
01633 for (i = start; i != stop; i += dir)
01634 {
01635 int num = group ? (*group)[i] : i;
01636 const char *nm = combos[i]->name.c_str();
01637 if (nm && search_name(nm, srch))
01638 break;
01639 }
01640 if (i == stop)
01641 return;
01642 while (i < index0)
01643 scroll(true);
01644 while (i >= index0 + info_cnt)
01645 scroll(false);
01646 int newsel = i - index0;
01647 if (newsel >= 0 && newsel < info_cnt)
01648 select(newsel);
01649 show();
01650 }
01651