/************************************************************************** Redraw overview canvas **************************************************************************/ gboolean overview_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data) { gpointer source = (can_client_change_view()) ? (gpointer)overview.window : (gpointer)radar_gfx_sprite; if (source) { cairo_surface_t *surface = (can_client_change_view()) ? overview.window->surface : radar_gfx_sprite->surface; cairo_set_source_surface(cr, surface, 0, 0); cairo_paint(cr); } return TRUE; }
/************************************************************************** ... **************************************************************************/ void scrollbar_scroll_callback(Widget w, XtPointer client_data, XtPointer position_val) { int position = XTPOINTER_TO_INT(position_val); int scroll_x, scroll_y, xstep, ystep; get_mapview_scroll_pos(&scroll_x, &scroll_y); get_mapview_scroll_step(&xstep, &ystep); if (!can_client_change_view()) { return; } if(w==map_horizontal_scrollbar) { if (position > 0) { scroll_x += xstep; } else { scroll_x -= xstep; } } else { if (position > 0) { scroll_y += ystep; } else { scroll_y -= ystep; } } set_mapview_scroll_pos(scroll_x, scroll_y); update_map_canvas_scrollbars(); }
static void xaw_key_open_science_report(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_REPORT, MENU_REPORT_SCIENCE)) { science_report_dialog_popup(FALSE); } }
static void xaw_key_open_messages(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_REPORT, MENU_REPORT_MESSAGES)) { meswin_dialog_popup(FALSE); } }
/**************************************************************************** Invoked when the key binding for report->top_five_cities is pressed. ****************************************************************************/ static void xaw_key_open_top_five(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_REPORT, MENU_REPORT_TOP_CITIES)) { send_report_request(REPORT_TOP_5_CITIES); } }
/**************************************************************************** Invoked when the key binding for government->worklists is pressed. ****************************************************************************/ static void xaw_key_open_worklists(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_GOVERNMENT, MENU_GOVERNMENT_WORKLISTS)) { popup_worklists_dialog(client.conn.playing); } }
/**************************************************************************** Invoked when the key binding for government->rates is pressed. ****************************************************************************/ static void xaw_key_open_rates(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_GOVERNMENT, MENU_GOVERNMENT_RATES)) { popup_rates_dialog(); } }
/**************************************************************************** Invoked when the key binding for government->find_city is pressed. ****************************************************************************/ static void xaw_key_open_find_city(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_GOVERNMENT, MENU_GOVERNMENT_FIND_CITY)) { popup_find_dialog(); } }
/**************************************************************************** Invoked when the key binding for government->revolution is pressed. ****************************************************************************/ static void xaw_key_open_revolution(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_GOVERNMENT, MENU_GOVERNMENT_REVOLUTION)) { popup_revolution_dialog(NULL); } }
/************************************************************************** ... **************************************************************************/ void map_canvas_expose(Widget w, XEvent *event, Region exposed, void *client_data) { Dimension width, height; bool map_resized; XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL); map_resized = map_canvas_resized(width, height); if (!can_client_change_view()) { if (!intro_gfx_sprite) { load_intro_gfx(); } if (height != scaled_intro_pixmap_height || width != scaled_intro_pixmap_width) { if (scaled_intro_pixmap) { XFreePixmap(display, scaled_intro_pixmap); } scaled_intro_pixmap=x_scale_pixmap(intro_gfx_sprite->pixmap, intro_gfx_sprite->width, intro_gfx_sprite->height, width, height, root_window); scaled_intro_pixmap_width=width; scaled_intro_pixmap_height=height; } if(scaled_intro_pixmap) XCopyArea(display, scaled_intro_pixmap, XtWindow(map_canvas), civ_gc, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height, event->xexpose.x, event->xexpose.y); return; } if(scaled_intro_pixmap) { XFreePixmap(display, scaled_intro_pixmap); scaled_intro_pixmap=0; scaled_intro_pixmap_height=0; } if (map_exists() && !map_resized) { /* First we mark the area to be updated as dirty. Then we unqueue * any pending updates, to make sure only the most up-to-date data * is written (otherwise drawing bugs happen when old data is copied * to screen). Then we draw all changed areas to the screen. */ unqueue_mapview_updates(FALSE); XCopyArea(display, mapview.store->pixmap, XtWindow(map_canvas), civ_gc, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height, event->xexpose.x, event->xexpose.y); } refresh_overview_canvas(); }
/************************************************************************** Refresh map canvas scrollbars **************************************************************************/ void update_map_canvas_scrollbars(void) { int scroll_x, scroll_y; get_mapview_scroll_pos(&scroll_x, &scroll_y); gtk_adjustment_set_value(map_hadj, scroll_x); gtk_adjustment_set_value(map_vadj, scroll_y); if (can_client_change_view()) { gtk_widget_queue_draw(overview_canvas); } }
/************************************************************************** Redraw map canvas. **************************************************************************/ gboolean map_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data) { if (can_client_change_view() && map_exists() && !mapview_is_frozen()) { /* First we mark the area to be updated as dirty. Then we unqueue * any pending updates, to make sure only the most up-to-date data * is written (otherwise drawing bugs happen when old data is copied * to screen). Then we draw all changed areas to the screen. */ unqueue_mapview_updates(FALSE); cairo_set_source_surface(cr, mapview.store->surface, 0, 0); cairo_paint(cr); } return TRUE; }
/************************************************************************** Map canvas exposed **************************************************************************/ gboolean map_canvas_expose(GtkWidget *w, GdkEventExpose *ev, gpointer data) { if (can_client_change_view() && map_exists() && !mapview_is_frozen()) { /* First we mark the area to be updated as dirty. Then we unqueue * any pending updates, to make sure only the most up-to-date data * is written (otherwise drawing bugs happen when old data is copied * to screen). Then we draw all changed areas to the screen. */ unqueue_mapview_updates(FALSE); gdk_draw_drawable(map_canvas->window, civ_gc, mapview.store->v.pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); } return TRUE; }
/************************************************************************** ... **************************************************************************/ gboolean overview_canvas_expose(GtkWidget *w, GdkEventExpose *ev, gpointer data) { if (!can_client_change_view()) { if (radar_gfx_sprite) { gdk_draw_drawable(overview_canvas->window, civ_gc, radar_gfx_sprite->pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); } return TRUE; } refresh_overview_canvas(); return TRUE; }
/************************************************************************** ... **************************************************************************/ void scrollbar_jump_callback(GtkAdjustment *adj, gpointer hscrollbar) { int scroll_x, scroll_y; if (!can_client_change_view()) { return; } get_mapview_scroll_pos(&scroll_x, &scroll_y); if (hscrollbar) { scroll_x = adj->value; } else { scroll_y = adj->value; } set_mapview_scroll_pos(scroll_x, scroll_y); }
/************************************************************************** ... **************************************************************************/ static void overview_mouse_press_callback(struct sw_widget *widget, const struct ct_point *pos, enum be_mouse_button button, int state, void *data) { int xtile, ytile; freelog(LOG_DEBUG, "press (%d,%d)", pos->x, pos->y); overview_to_map_pos(&xtile,&ytile,pos->x,pos->y); freelog(LOG_DEBUG, " --> (%d,%d)", xtile, ytile); if (can_client_change_view() && button == 3) { center_tile_mapcanvas(map_pos_to_tile(xtile, ytile)); } /* FIXME else if (can_client_issue_orders() && ev->button == 1) { do_unit_goto(xtile, ytile); } */ }
/************************************************************************** Button pressed at overview **************************************************************************/ gboolean butt_down_overviewcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data) { int xtile, ytile; if (ev->type != GDK_BUTTON_PRESS) return TRUE; /* Double-clicks? Triple-clicks? No thanks! */ overview_to_map_pos(&xtile, &ytile, ev->x, ev->y); if (can_client_change_view() && (ev->button == 3)) { center_tile_mapcanvas(map_pos_to_tile(xtile, ytile)); } else if (can_client_issue_orders() && (ev->button == 1)) { do_map_click(map_pos_to_tile(xtile, ytile), (ev->state & GDK_SHIFT_MASK) ? SELECT_APPEND : SELECT_POPUP); } return TRUE; }
/************************************************************************** ... **************************************************************************/ void overview_canvas_expose(Widget w, XEvent *event, Region exposed, void *client_data) { Dimension height, width; if (!can_client_change_view()) { if (radar_gfx_sprite) { XCopyArea(display, radar_gfx_sprite->pixmap, XtWindow(overview_canvas), civ_gc, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height, event->xexpose.x, event->xexpose.y); } return; } XtVaGetValues(w, XtNheight, &height, XtNwidth, &width, NULL); refresh_overview_from_canvas(); }
/************************************************************************** ... **************************************************************************/ void mapctrl_btn_mapcanvas(XEvent *event) { XButtonEvent *ev=&event->xbutton; struct tile *ptile = canvas_pos_to_tile(ev->x, ev->y); if (!can_client_change_view()) { return; } if (ev->button == Button1 && (ev->state & ControlMask)) { action_button_pressed(ev->x, ev->y, SELECT_SEA); } else if (ev->button == Button1) { action_button_pressed(ev->x, ev->y, SELECT_POPUP); } else if (ev->button == Button2 && ptile) { popit(ev->x, ev->y, ptile); } else if (ev->button == Button3 && (ev->state & ControlMask)) { action_button_pressed(ev->x, ev->y, SELECT_LAND); } else if (ev->button == Button3) { recenter_button_pressed(ev->x, ev->y); } }
/************************************************************************** ... **************************************************************************/ void mapctrl_btn_overviewcanvas(XEvent *event) { int map_x, map_y; struct tile *ptile; XButtonEvent *ev = &event->xbutton; if (!can_client_change_view()) { return; } overview_to_map_pos(&map_x, &map_y, event->xbutton.x, event->xbutton.y); ptile = map_pos_to_tile(map_x, map_y); if (!ptile) { return; } if(ev->button==Button1) do_map_click(ptile, SELECT_POPUP); else if(ev->button==Button3) center_tile_mapcanvas(ptile); }
/************************************************************************** ... **************************************************************************/ gboolean map_canvas_expose(GtkWidget *w, GdkEventExpose *ev, gpointer data) { static bool cleared = FALSE; if (!can_client_change_view()) { if (!cleared) { gtk_widget_queue_draw(w); cleared = TRUE; } map_center = TRUE; } else { if (map_exists()) { /* do we have a map at all */ /* First we mark the area to be updated as dirty. Then we unqueue * any pending updates, to make sure only the most up-to-date data * is written (otherwise drawing bugs happen when old data is copied * to screen). Then we draw all changed areas to the screen. */ unqueue_mapview_updates(FALSE); gdk_draw_drawable(map_canvas->window, civ_gc, mapview.store->v.pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); cleared = FALSE; } else { if (!cleared) { gtk_widget_queue_draw(w); cleared = TRUE; } } if (!map_center) { center_on_something(); map_center = FALSE; } } map_configure = FALSE; return TRUE; }
/************************************************************************** ... **************************************************************************/ void scrollbar_jump_callback(Widget w, XtPointer client_data, XtPointer percent_ptr) { float percent=*(float*)percent_ptr; int xmin, ymin, xmax, ymax, xsize, ysize; int scroll_x, scroll_y; if (!can_client_change_view()) { return; } get_mapview_scroll_window(&xmin, &ymin, &xmax, &ymax, &xsize, &ysize); get_mapview_scroll_pos(&scroll_x, &scroll_y); if(w==map_horizontal_scrollbar) { scroll_x = xmin + (percent * (xmax - xmin)); } else { scroll_y = ymin + (percent * (ymax - ymin)); } set_mapview_scroll_pos(scroll_x, scroll_y); }
/**************************************************************************** Invoked when the key binding for report->wonders is pressed. ****************************************************************************/ static void xaw_key_open_wonders(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_REPORT, MENU_REPORT_WOW)) send_report_request(REPORT_WONDERS_OF_THE_WORLD); }
static void xaw_key_open_spaceship(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_REPORT, MENU_REPORT_SPACESHIP)) popup_spaceship_dialog(client.conn.playing); }
/************************************************************************** Handle all mouse button press on canvas. Future feature: User-configurable mouse clicks. **************************************************************************/ gboolean butt_down_mapcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data) { struct city *pcity = NULL; struct tile *ptile = NULL; if (editor_is_active()) { return handle_edit_mouse_button_press(ev); } if (!can_client_change_view()) { return TRUE; } gtk_widget_grab_focus(map_canvas); ptile = canvas_pos_to_tile(ev->x, ev->y); pcity = ptile ? tile_city(ptile) : NULL; switch (ev->button) { case 1: /* LEFT mouse button */ /* <SHIFT> + <CONTROL> + LMB : Adjust workers. */ if ((ev->state & GDK_SHIFT_MASK) && (ev->state & GDK_CONTROL_MASK)) { adjust_workers_button_pressed(ev->x, ev->y); } /* <CONTROL> + LMB : Quickselect a sea unit. */ else if (ev->state & GDK_CONTROL_MASK) { action_button_pressed(ev->x, ev->y, SELECT_SEA); } /* <SHIFT> + LMB: Append focus unit. */ else if (ptile && (ev->state & GDK_SHIFT_MASK)) { action_button_pressed(ev->x, ev->y, SELECT_APPEND); } /* <ALT> + LMB: popit (same as middle-click) */ /* FIXME: we need a general mechanism for letting freeciv work with * 1- or 2-button mice. */ else if (ptile && (ev->state & GDK_MOD1_MASK)) { popit(ev, ptile); } /* LMB in Area Selection mode. */ else if(tiles_hilited_cities) { if (ptile) { toggle_tile_hilite(ptile); } } /* Plain LMB click. */ else { action_button_pressed(ev->x, ev->y, SELECT_POPUP); } break; case 2: /* MIDDLE mouse button */ /* <CONTROL> + MMB: Wake up sentries. */ if (ev->state & GDK_CONTROL_MASK) { wakeup_button_pressed(ev->x, ev->y); } /* Plain Middle click. */ else if (ptile) { popit(ev, ptile); } break; case 3: /* RIGHT mouse button */ /* <CONTROL> + <ALT> + RMB : insert city or tile chat link. */ /* <CONTROL> + <ALT> + <SHIFT> + RMB : insert unit chat link. */ if (ptile && (ev->state & GDK_MOD1_MASK) && (ev->state & GDK_CONTROL_MASK)) { inputline_make_chat_link(ptile, (ev->state & GDK_SHIFT_MASK) != 0); } /* <SHIFT> + <ALT> + RMB : Show/hide workers. */ else if ((ev->state & GDK_SHIFT_MASK) && (ev->state & GDK_MOD1_MASK)) { key_city_overlay(ev->x, ev->y); } /* <SHIFT + CONTROL> + RMB: Paste Production. */ else if ((ev->state & GDK_SHIFT_MASK) && (ev->state & GDK_CONTROL_MASK) && pcity != NULL) { clipboard_paste_production(pcity); cancel_tile_hiliting(); } /* <SHIFT> + RMB on city/unit: Copy Production. */ /* If nothing to copy, fall through to rectangle selection. */ else if (ev->state & GDK_SHIFT_MASK && clipboard_copy_production(ptile)) { /* Already done the copy */ } /* <CONTROL> + RMB : Quickselect a land unit. */ else if (ev->state & GDK_CONTROL_MASK) { action_button_pressed(ev->x, ev->y, SELECT_LAND); } /* Plain RMB click. Area selection. */ else { /* A foolproof user will depress button on canvas, * release it on another widget, and return to canvas * to find rectangle still active. */ if (rectangle_active) { release_right_button(ev->x, ev->y, (ev->state & GDK_SHIFT_MASK) != 0); return TRUE; } if (hover_state == HOVER_NONE) { anchor_selection_rectangle(ev->x, ev->y); rbutton_down = TRUE; /* causes rectangle updates */ } } break; default: break; } return TRUE; }
static void xaw_key_open_players(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_REPORT, MENU_REPORT_PLAYERS)) popup_players_dialog(FALSE); }
static void xaw_key_open_demographics(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_REPORT, MENU_REPORT_DEMOGRAPHIC)) send_report_request(REPORT_DEMOGRAPHIC); }
static void xaw_key_open_goto_airlift(Widget w, XEvent *event, String *argv, Cardinal *argc) { if (can_client_change_view() && is_menu_item_active(MENU_ORDER, MENU_ORDER_GOTO_CITY)) popup_goto_dialog(); }