/* field.c - Created by Giampiero Caprino This file is part of Train Director Train Director is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. Train Director is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Train Director; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #if !defined(__unix__) #include #endif #include "trsim.h" #include "gtkui.h" #define TOOLMULT 3 #include "itracks.h" /* icons for tools */ #include "iswitch.h" #include "isignals.h" #include "itools.h" #include "iactions.h" void track_dialogue(Track *t); void repaint_all_tools(void); void select_tool(int i); void append_button(); void init_tool_layout(void); extern int ignore_cliprect; GdkFont *smallfont; struct _itin { GtkWidget *table; /* parent widget for itinerary table */ GtkWidget *bcol; GtkWidget *scroll; GtkCList *clist; int row; /* selected row */ } itin; extern int is_windows; extern int screen_width; grid *current_grid, *field_grid, *tools_grid; int current_tool; int current_toolset = 1; extern Track *tool_tracks, *tool_switches, *tool_signals, *tool_misc, *tool_actions; extern struct edittools tooltbltracks[], tooltblswitches[], tooltblsignals[], tooltblmisc[], tooltblactions[]; int updating_all; int first_time = 1; int show_grid = 0; int itin_start_x, itin_start_y; int ntoolrows = 2; guchar colortable[12][3] = { { 0, 0, 0 }, { 255, 255, 255 }, { 0, 255, 0 }, { 255, 255, 0 }, { 255, 0, 0 }, { 255, 128, 0 }, { 255, 128, 128 }, { 128, 128, 128 }, { 192, 192, 192 }, { 64, 64, 64 }, { 0, 0, 128 }, { 0, 255, 255 } }; void getcolor_rgb(int col, int *r, int *g, int *b) { if(col < 0 || col > 11) return; *r = colortable[col][0]; *g = colortable[col][1]; *b = colortable[col][2]; } void clear_field(void) { grid *g; GtkStyle *style; if(editing) invalidate_field(); g = field_grid; style = gtk_widget_get_style( g->drawing_area ); gdk_gc_set_foreground(g->gc, &style->bg[GTK_STATE_NORMAL]); gdk_draw_rectangle(g->pixmap, g->gc, TRUE, cliprect.left * HGRID * g->hmult, cliprect.top * VGRID * g->vmult, (cliprect.right - cliprect.left + 1) * HGRID * g->hmult, (cliprect.bottom - cliprect.top + 1) * VGRID * g->vmult ); } void draw_all_pixmap(void) { grid *g; g = field_grid; gdk_draw_pixmap(g->drawing_area->window, g->gc, g->pixmap, cliprect.left * HGRID * g->hmult, cliprect.top * VGRID * g->vmult, cliprect.left * HGRID * g->hmult, cliprect.top * VGRID * g->vmult, cliprect.right * HGRID * g->hmult, cliprect.bottom * VGRID * g->vmult); } void grid_paint(void) { int x, y; grid *g = field_grid; gdk_rgb_gc_set_foreground(g->gc, (colortable[9][0] << 16) | (colortable[9][1] << 8) | (colortable[9][2])); for(x = 0; x < 2000; x += HGRID) for(y = 0; y < 1000; y += VGRID) if(x >= cliprect.left * HGRID && x <= cliprect.right * HGRID && y >= cliprect.top * VGRID && y <= cliprect.bottom * VGRID) gdk_draw_point(g->pixmap, g->gc, x, y); } void repaint_all(void) { current_grid = field_grid; if(!editing && cliprect.top > cliprect.bottom) return; /* no changes since last update */ if(ignore_cliprect || editing) clear_field(); updating_all = 1; if(show_grid) grid_paint(); layout_paint(layout); trains_paint(stranded); trains_paint(schedule); updating_all = 0; draw_all_pixmap(); reset_clip_rect(); } void repaint_field(void) { grid *tmp; tmp = current_grid; current_grid = field_grid; repaint_all(); current_grid = tmp; } /* Create a new backing pixmap of the appropriate size */ static gint configure_event( GtkWidget *widget, GdkEventConfigure *event ) { if(field_grid->pixmap) return 0; invalidate_field(); /* gdk_pixmap_unref(pixmap); */ field_grid->pixmap = gdk_pixmap_new(widget->window, 2000 /* widget->allocation.width */, 1000 /* widget->allocation.height */, -1); field_grid->gc = gdk_gc_new(field_grid->drawing_area->window); clear_field(); return TRUE; } /* Redraw the screen from the backing pixmap */ gint expose_event( GtkWidget *widget, GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], field_grid->pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } void update_rectangle_at(int x, int y) { GdkRectangle update_rect; if(updating_all) return; x *= HGRID * current_grid->hmult; y *= VGRID * current_grid->vmult; update_rect.x = x; update_rect.y = y; update_rect.width = HGRID * current_grid->hmult; update_rect.height = VGRID * current_grid->vmult; gtk_widget_draw(current_grid->drawing_area, &update_rect); } void tr_fillrect(int x, int y) { GtkStyle *style; grid *g; x *= HGRID * current_grid->hmult; y *= VGRID * current_grid->vmult; g = current_grid; style = gtk_widget_get_style( g->drawing_area ); gdk_gc_set_foreground(g->gc, &style->bg[GTK_STATE_NORMAL]); gdk_draw_rectangle(g->pixmap, current_grid->gc, TRUE, x, y, HGRID * g->hmult, VGRID * g->vmult); } void draw_layout(int x0, int y0, VLines *p, grcolor col) { GdkRectangle update_rect; int x = x0 * HGRID * current_grid->hmult; int y = y0 * VGRID * current_grid->vmult; gdk_rgb_gc_set_foreground(current_grid->gc, (colortable[col][0] << 16) | (colortable[col][1] << 8) | (colortable[col][2])); while(p->x0 >= 0) { gdk_draw_line(current_grid->pixmap, current_grid->gc, x + p->x0 * current_grid->hmult, y + p->y0 * current_grid->vmult, x + p->x1 * current_grid->hmult, y + p->y1 * current_grid->vmult); ++p; } update_rectangle_at(x0, y0); } void draw_segments(int x0, int y0, SegDir *p, grcolor col) { GdkRectangle update_rect; int x = x0 * HGRID * current_grid->hmult; int y = y0 * VGRID * current_grid->vmult; int hx; int hy; gdk_rgb_gc_set_foreground(current_grid->gc, (colortable[col][0] << 16) | (colortable[col][1] << 8) | (colortable[col][2])); hx = current_grid->hmult * HGRID / 2; hy = current_grid->vmult * VGRID / 2; while(*p != SEG_END) { switch(*p) { case SEG_N: gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y, x + hx, y + hy); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx + 1, y, x + hx + 1, y + hy); break; case SEG_NE: gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy - 1, x + hx * 2 - 1, y); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy, x + hx * 2, y); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy + 1, x + hx * 2, y + 1); break; case SEG_E: gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy, x + hx * 2, y + hy); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy + 1, x + hx * 2, y + hy + 1); break; case SEG_SE: gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx + 1, y + hy, x + hx * 2, y + hy * 2 - 1); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy, x + hx * 2, y + hy * 2); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy + 1, x + hx * 2 - 1, y + hy * 2); break; case SEG_S: gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx, y + hy, x + hx, y + hy * 2); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + hx + 1, y + hy, x + hx + 1, y + hy * 2); break; case SEG_SW: gdk_draw_line(current_grid->pixmap, current_grid->gc, x, y + hy * 2 - 1, x + hx - 1, y + hy); gdk_draw_line(current_grid->pixmap, current_grid->gc, x, y + hy * 2, x + hx, y + hy); gdk_draw_line(current_grid->pixmap, current_grid->gc, x + 1, y + hy * 2, x + hx, y + hy + 1); break; case SEG_W: gdk_draw_line(current_grid->pixmap, current_grid->gc, x, y + hy, x + hx, y + hy); gdk_draw_line(current_grid->pixmap, current_grid->gc, x, y + hy + 1, x + hx, y + hy + 1); break; case SEG_NW: gdk_draw_line(current_grid->pixmap, current_grid->gc, x + 1, y, x + hx, y + hy - 1); gdk_draw_line(current_grid->pixmap, current_grid->gc, x, y, x + hx, y + hy); gdk_draw_line(current_grid->pixmap, current_grid->gc, x, y + 1, x + hx - 1, y + hy); break; } ++p; } update_rectangle_at(x0, y0); } void *get_pixmap_file(char *fname) { GdkPixmap *pmap; GdkPixmap *mask; GtkStyle *style; char *p; char buff[256]; strcpy(buff, fname); for(p = buff; *p; ++p) if(*p >= 'A' && *p <= 'Z') *p += ' '; style = gtk_widget_get_style( current_grid->drawing_area ); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)fname ); if(pmap) return((void *)pmap); for(p = fname + strlen(fname); p >= fname; --p) if(*p == '\\' || *p == '/' || *p == ':') { ++p; break; } if(p < fname) p = fname; pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)p ); if(pmap) return((void *)pmap); #if defined(__unix__) sprintf(buff, "%s/%s", curpath, p); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)buff); #endif if(pmap) return((void *)pmap); if(getenv("TDICONDIR")) { sprintf(buff, "%s/%s", getenv("TDICONDIR"), p); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)buff ); if(pmap) return((void *)pmap); } #if defined(__unix__) /*tdicons in scenario directory */ sprintf(buff, "%s/tdicons/%s", curpath, p); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)buff ); if(pmap) return((void *)pmap); if(getenv("TDHOME") != NULL) { /* in TDHOME/tdicons */ sprintf(buff,"%s/tdicons/%s", getenv("TDHOME"), p); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)buff ); } else { sprintf(buff, "tdicons/%s", p); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)buff ); } #else sprintf(buff, "tdicons/%s", p); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)buff ); if(pmap) return((void *)pmap); sprintf(buff, "C:/tdicons/%s", p); pmap = gdk_pixmap_create_from_xpm(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar *)buff ); #endif return((void *)pmap); } void *get_pixmap(const char **map) { GdkPixmap *pmap; GdkPixmap *mask; GtkStyle *style; style = gtk_widget_get_style( current_grid->drawing_area ); pmap = gdk_pixmap_create_from_xpm_d(current_grid->drawing_area->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar **)map ); return((void *)pmap); } void draw_pixmap(int x0, int y0, void *map) { GdkPixmap *pmap = (GdkPixmap *)map; GtkStyle *style; GdkRectangle update_rect; int x = x0 * HGRID * current_grid->hmult; int y = y0 * VGRID * current_grid->vmult; if(!current_grid->pixmap) return; if(!current_grid->gc) current_grid->gc = gdk_gc_new(current_grid->drawing_area->window); style = gtk_widget_get_style( current_grid->drawing_area); if(current_grid == tools_grid && y0) { x += HGRID / 2 * tools_grid->hmult; y += VGRID / 2 * tools_grid->vmult; } gdk_draw_pixmap(current_grid->pixmap, style->black_gc, pmap, 0, 0, x, y, -1, -1); if(updating_all) return; update_rect.x = x; update_rect.y = y; update_rect.width = 16 * current_grid->hmult; update_rect.height = 11 * current_grid->vmult; gtk_widget_draw(current_grid->drawing_area, &update_rect); } void draw_layout_text1(int x, int y, char *text, int small) { GdkRectangle update_rect; GtkStyle *style; GdkFont *font; y -= is_windows; /* fix incompatibility in Win GTK */ if(/*small && */current_grid == tools_grid && !strcmp(text, " A")) { x -= 1; } update_rect.x = x * HGRID * current_grid->hmult; update_rect.y = y * VGRID * current_grid->vmult; style = current_grid->drawing_area->style; font = style->font; if(small) font = smallfont; if(current_grid == tools_grid) { #if defined(__unix__) update_rect.y -= VGRID * tools_grid->vmult / 2; #else update_rect.y += VGRID * tools_grid->vmult / 2; #endif update_rect.width = HGRID * tools_grid->hmult; update_rect.height = VGRID * tools_grid->vmult; } else { update_rect.width = gdk_string_width(font, text); update_rect.height = gdk_string_height(font, text); } gdk_draw_string(current_grid->pixmap, font, style->black_gc, update_rect.x, update_rect.y + update_rect.height, text); if(updating_all) return; gtk_widget_draw(current_grid->drawing_area, &update_rect); } void draw_link(int x0, int y0, int x1, int y1, int color) { int hx; int hy; x0 = x0 * HGRID * current_grid->hmult; y0 = y0 * VGRID * current_grid->vmult; x1 = x1 * HGRID * current_grid->hmult; y1 = y1 * VGRID * current_grid->vmult; gdk_rgb_gc_set_foreground(current_grid->gc, (colortable[color][0] << 16) | (colortable[color][1] << 8) | (colortable[color][2])); hx = current_grid->hmult * HGRID / 2; hy = current_grid->vmult * VGRID / 2; gdk_draw_line(current_grid->pixmap, current_grid->gc, x0 + hx, y0 + hy, x1 + hx, y1 + hy); } void draw_layout_text(int x, int y, char *text) { draw_layout_text1(x, y, text, 0); } static gint button_press_event( GtkWidget *widget, GdkEventButton *event ) { int x, y; GdkModifierType state; current_grid = field_grid; x = event->x / HGRID; y = event->y / VGRID; if(!editing && !editing_itinerary && (event->state & GDK_SHIFT_MASK)) { if(track_shift_selected(x, y)) return TRUE; if(event->button == 1) { itin_start_x = x; itin_start_y = y; } else try_itinerary(itin_start_x, itin_start_y, x, y); return TRUE; } if(!editing && !editing_itinerary && (event->state & GDK_CONTROL_MASK)) { if(track_control_selected(x, y)) return TRUE; } if(event->button == 1 && field_grid->pixmap) { if(editing) track_place(x, y); else track_selected(x, y); } if(event->button > 1 && field_grid->pixmap) { if(editing_itinerary) do_itinerary_dialog(x, y); else if(editing) track_properties(x, y); else track_selected1(x, y); } return TRUE; } static gint motion_notify_event( GtkWidget *widget, GdkEventMotion *event ) { int x, y; GdkModifierType state; if(event->is_hint) gdk_window_get_pointer(event->window, &x, &y, &state); else { x = event->x; y = event->y; state = event->state; } pointer_at(x / HGRID, y / VGRID); return TRUE; } /* Create the drawing area */ int create_draw(GtkWidget *window) { GtkAdjustment *adj; grid *g; g = (grid *)calloc(sizeof(grid), 1); g->hmult = 1; g->vmult = 1; field_grid = g; current_grid = g; g->drawing_area = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(g->drawing_area), 2000, 1000); /* pack the drawing area into the scrolled window */ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(window), g->drawing_area); #if 0 adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(window)); gtk_signal_connect(GTK_OBJECT(adj), "value_changed", (GtkSignalFunc) scroll_changed, NULL); #endif gtk_widget_show(g->drawing_area); /* Signals used to handle backing pixmap */ gtk_signal_connect(GTK_OBJECT(g->drawing_area), "expose_event", (GtkSignalFunc) expose_event, NULL); gtk_signal_connect(GTK_OBJECT(g->drawing_area),"configure_event", (GtkSignalFunc) configure_event, NULL); /* Event signals */ gtk_signal_connect(GTK_OBJECT(g->drawing_area), "motion_notify_event", (GtkSignalFunc) motion_notify_event, NULL); gtk_signal_connect(GTK_OBJECT(g->drawing_area), "button_press_event", (GtkSignalFunc) button_press_event, NULL); gtk_widget_set_events(g->drawing_area, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); return 0; } int create_field(GtkWidget *window, GtkWidget *vbox) { GtkWidget *scrolled_window; GtkWidget *table; GtkWidget *button; char buffer[32]; int i, j; /* create a new scrolled window. */ scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 1); /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS. * GTK_POLICY_AUTOMATIC will automatically decide whether you need * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars * there. The first one is the horizontal scrollbar, the second, * the vertical. */ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); /* The dialog window is created with a vbox packed into it. */ gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0); gtk_widget_show(scrolled_window); create_draw(scrolled_window); return(0); } /* Create a new backing pixmap of the appropriate size */ static gint tools_configure_event( GtkWidget *widget, GdkEventConfigure *event ) { if(tools_grid->pixmap) return 0; /* gdk_pixmap_unref(pixmap); */ tools_grid->pixmap = gdk_pixmap_new(widget->window, 2000 /* widget->allocation.width */, ntoolrows * tools_grid->vmult * VGRID, -1); tools_grid->gc = gdk_gc_new(current_grid->drawing_area->window); repaint_all_tools(); return 1; } void repaint_all_tools(void) { int x; static void *tracks_pixmap, *switches_pixmap, *signals_pixmap, *tools_pixmap, *actions_pixmap; if(!tracks_pixmap) { tracks_pixmap = get_pixmap(tracks_xpm); switches_pixmap = get_pixmap(switches_xpm); signals_pixmap = get_pixmap(signals_xpm); tools_pixmap = get_pixmap(tools_xpm); actions_pixmap = get_pixmap(actions_xpm); } gdk_draw_rectangle(tools_grid->pixmap, tools_grid->drawing_area->style->bg_gc[ GTK_WIDGET_STATE(field_grid->drawing_area)], TRUE, 0, 0, 2000, ntoolrows * tools_grid->vmult * VGRID); ++editing; updating_all = 1; current_grid = tools_grid; switch(current_toolset) { case 1: layout_paint(tool_tracks); break; case 2: layout_paint(tool_switches); break; case 3: layout_paint(tool_signals); break; case 4: layout_paint(tool_misc); break; case 5: layout_paint(tool_actions); break; } // layout_paint(tool_layout); gdk_rgb_gc_set_foreground( tools_grid->drawing_area->style->fg_gc[GTK_WIDGET_STATE(tools_grid->drawing_area)], 0x00ffff); for(x = 0; tooltbl[x].type != -1; ++x) gdk_draw_rectangle(tools_grid->pixmap, tools_grid->drawing_area->style->fg_gc[GTK_WIDGET_STATE(tools_grid->drawing_area)], FALSE, tooltbl[x].x * tools_grid->hmult * HGRID, tooltbl[x].y * tools_grid->vmult * VGRID, HGRID * tools_grid->hmult - 1, VGRID * tools_grid->vmult - 1); draw_pixmap(1, 0, tracks_pixmap); draw_pixmap(2, 0, switches_pixmap); draw_pixmap(3, 0, signals_pixmap); draw_pixmap(4, 0, tools_pixmap); draw_pixmap(5, 0, actions_pixmap); gdk_rgb_gc_set_foreground( tools_grid->drawing_area->style->fg_gc[GTK_WIDGET_STATE(tools_grid->drawing_area)], 0x000000); updating_all = 0; --editing; gdk_draw_pixmap(tools_grid->drawing_area->window, tools_grid->drawing_area->style->fg_gc[ GTK_WIDGET_STATE(tools_grid->drawing_area)], tools_grid->pixmap, 0, 0, 0, 0, 1000, ntoolrows * tools_grid->vmult * VGRID); } /* Redraw the screen from the backing pixmap */ gint tools_expose_event( GtkWidget *widget, GdkEventExpose *event ) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], tools_grid->pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE; } void select_tool(int i) { Track *t; grid *old; GdkRectangle update_rect; int x, y; old = current_grid; current_grid = tools_grid; if(tooltbl[i].type == MACRO) { if(tooltbl[i].direction == 0) { if(!macro_select()) { current_grid = old; return; } ++i; } } /* if(current_tool >= 0) track_paint(tooltbl[current_tool].trk); else { tr_fillrect(0, 0); update_rectangle_at(0, 0); } */ repaint_all_tools(); current_tool = i; if(i > 0) { t = tooltbl[i].trk; x = t->x * HGRID * current_grid->hmult; y = t->y * VGRID * current_grid->vmult; } else { x = 0; y = 0; } gdk_draw_rectangle(current_grid->pixmap, tools_grid->drawing_area->style->black_gc, FALSE, x, y, HGRID * tools_grid->hmult - 1, VGRID * tools_grid->vmult - 1); y = 0; x = current_toolset * VGRID * current_grid->vmult; gdk_draw_rectangle(current_grid->pixmap, tools_grid->drawing_area->style->black_gc, FALSE, x, y, HGRID * tools_grid->hmult - 1, VGRID * tools_grid->vmult - 1); update_rect.x = 0; update_rect.y = 0; update_rect.width = 1000/*HGRID * tools_grid->vmult*/; update_rect.height = ntoolrows * tools_grid->vmult * VGRID /*VGRID * tools_grid->vmult*/; gtk_widget_draw(tools_grid->drawing_area, &update_rect); current_grid = old; } void hide_tooltable(void) { gtk_widget_hide(tools_grid->drawing_area); } void show_tooltable(void) { gtk_widget_show(tools_grid->drawing_area); select_tool(current_tool); repaint_all(); } void hide_itinerary(void) { gtk_widget_hide(itin.table); } void show_itinerary(void) { Itinerary *it; int i; char buff1[80]; char buff2[256]; char *cols[3] = { buff1, buff2, NULL }; gtk_clist_clear(itin.clist); gtk_clist_freeze(itin.clist); for(it = itineraries; it; it = it->next) { sprintf(buff1, "%s", it->name); sprintf(buff2, "%s -> %s", it->signame, it->endsig); gtk_clist_append(itin.clist, cols); } gtk_clist_thaw(itin.clist); gtk_widget_show_all(itin.table); repaint_all(); } static gint tool_button_press_event( GtkWidget *widget, GdkEventButton *event ) { int x, y; int i; if(event->button == 1 && tools_grid && tools_grid->pixmap) { x = event->x / (HGRID * tools_grid->hmult); y = event->y / (HGRID * tools_grid->vmult); if(y == 0) { switch(x) { case 1: current_toolset = x; tooltbl = tooltbltracks; select_tool(0); return TRUE; case 2: current_toolset = x; tooltbl = tooltblswitches; select_tool(0); return TRUE; case 3: current_toolset = x; tooltbl = tooltblsignals; select_tool(0); return TRUE; case 4: current_toolset = x; tooltbl = tooltblmisc; select_tool(0); return TRUE; case 5: current_toolset = x; tooltbl = tooltblactions; select_tool(0); return TRUE; } } for(i = 0; tooltbl[i].type != -1; ++i) if(tooltbl[i].x == x && tooltbl[i].y == y) { break; } if(tooltbl[i].type == -1) return TRUE; select_tool(i); } return TRUE; } void create_toolbox(GtkWidget *window, GtkWidget *vbox) { grid *g; Track *t; int i; g = (grid *)calloc(sizeof(grid), 1); tools_grid = g; g->hmult = TOOLMULT; g->vmult = TOOLMULT; g->drawing_area = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(g->drawing_area), 2000, ntoolrows * VGRID * TOOLMULT); gtk_signal_connect(GTK_OBJECT(g->drawing_area), "button_press_event", (GtkSignalFunc) tool_button_press_event, NULL); gtk_signal_connect(GTK_OBJECT(g->drawing_area), "expose_event", (GtkSignalFunc) tools_expose_event, NULL); gtk_signal_connect(GTK_OBJECT(g->drawing_area), "configure_event", (GtkSignalFunc) tools_configure_event, NULL); gtk_widget_set_events(g->drawing_area, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); gtk_box_pack_start(GTK_BOX(vbox), g->drawing_area, FALSE, FALSE, 0); smallfont = gdk_font_load("-adobe-*-medium-r-normal--10-*-*-*-*-*-*-*"); init_tool_layout(); } static gint itin_select_event(GtkWidget *clist, gint row, gint column, GdkEventButton *event, gpointer data) { itin.row = row; return 0; } gint delete_itin_cb(GtkWidget *btn, GtkWidget *window) { Itinerary *it; int i; if(itin.row == -1) return FALSE; it = itineraries; for(i = 0; it && i < itin.row; ++i, it = it->next); if(!it) return FALSE; delete_itinerary(it); show_itinerary(); return TRUE; } void create_itinerary_table(GtkWidget *window, GtkWidget *vbox) { GtkWidget *lbl; int i; static char *en_titles[] = { "Name", "Sections", NULL }; char *titles[3]; for(i = 0; en_titles[i]; ++i) titles[i] = L(en_titles[i]); itin.table = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(vbox), itin.table, FALSE, FALSE, 0); itin.bcol = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(itin.table), itin.bcol, FALSE, FALSE, 0); append_button(itin.bcol, "Delete", delete_itin_cb, NULL); /* Create a scrolled window to pack the CList widget into */ itin.scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(itin.scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_box_pack_start(GTK_BOX(itin.table), itin.scroll, TRUE, TRUE, 0); itin.clist = (GtkCList *)gtk_clist_new_with_titles(2, titles); /* When a selection is made, we want to know about it. The callback * used is selection_made, and its code can be found further down */ gtk_signal_connect(GTK_OBJECT(itin.clist), "select_row", GTK_SIGNAL_FUNC(itin_select_event), NULL); /* It isn't necessary to shadow the border, but it looks nice :) */ gtk_clist_set_shadow_type(itin.clist, GTK_SHADOW_OUT); /* What however is important, is that we set the column widths as * they will never be right otherwise. Note that the columns are * numbered from 0 and up (to 1 in this case). */ gtk_clist_set_column_width(itin.clist, 0, 50); gtk_clist_set_column_width(itin.clist, 1, 300); /* Add the CList widget to the vertical box and show it. */ gtk_container_add(GTK_CONTAINER(itin.scroll), GTK_WIDGET(itin.clist)); itin.row = -1; }