/************************************************************************** Refresh (update) the spaceship dialog for the given player. **************************************************************************/ void refresh_spaceship_dialog(struct player *pPlayer) { struct SMALL_DLG *pSpaceShp; struct widget *pBuf; if (!(pSpaceShp = get_spaceship_dialog(pPlayer))) { return; } /* launch button */ pBuf = pSpaceShp->pEndWidgetList->prev->prev; if (victory_enabled(VC_SPACERACE) && pPlayer == client.conn.playing && pPlayer->spaceship.state == SSHIP_STARTED && pPlayer->spaceship.success_rate > 0.0) { set_wstate(pBuf, FC_WS_NORMAL); } /* update text info */ pBuf = pBuf->prev; copy_chars_to_string16(pBuf->string16, get_spaceship_descr(&pPlayer->spaceship)); /* ------------------------------------------ */ /* redraw */ redraw_group(pSpaceShp->pBeginWidgetList, pSpaceShp->pEndWidgetList, 0); widget_mark_dirty(pSpaceShp->pEndWidgetList); flush_dirty(); }
/************************************************************************** Universal redraw Group of Widget function. Function is optimized to WindowGroup: start draw from 'pEnd' and stop on 'pBegin', in theory 'pEnd' is window widget; **************************************************************************/ Uint16 redraw_group(const struct widget *pBeginGroupWidgetList, const struct widget *pEndGroupWidgetList, int add_to_update) { Uint16 count = 0; struct widget *pTmpWidget = (struct widget *) pEndGroupWidgetList; while (pTmpWidget) { if ((get_wflags(pTmpWidget) & WF_HIDDEN) != WF_HIDDEN) { widget_redraw(pTmpWidget); if (add_to_update) { widget_mark_dirty(pTmpWidget); } count++; } if (pTmpWidget == pBeginGroupWidgetList) { break; } pTmpWidget = pTmpWidget->prev; } return count; }
/************************************************************************** Undraw and destroy Window Group The Trick is simple. We undraw only last member of group: the window. **************************************************************************/ void popdown_window_group_dialog(struct widget *pBeginGroupWidgetList, struct widget *pEndGroupWidgetList) { if ((pBeginGroupWidgetList) && (pEndGroupWidgetList)) { widget_mark_dirty(pEndGroupWidgetList); remove_gui_layer(pEndGroupWidgetList->dst); del_group(pBeginGroupWidgetList, pEndGroupWidgetList); } }
/************************************************************************** ... **************************************************************************/ void undraw_group(struct widget *pBeginGroupWidgetList, struct widget *pEndGroupWidgetList) { struct widget *pTmpWidget = pEndGroupWidgetList; while (pTmpWidget) { widget_undraw(pTmpWidget); widget_mark_dirty(pTmpWidget); if (pTmpWidget == pBeginGroupWidgetList) { break; } pTmpWidget = pTmpWidget->prev; } }
/************************************************************************** Do default Widget action when pressed, and then call widget callback function. example for Button: set flags FW_Pressed redraw button ( pressed ) refresh screen ( to see result ) wait 300 ms ( to see result :) If exist (button callback function) then call (button callback function) Function normal return Widget ID. NOTE: NOZERO return of this function deterninate exit of MAIN_SDL_GAME_LOOP if ( pWidget->action ) if ( pWidget->action(pWidget) ) ID = 0; if widget callback function return = 0 then return NOZERO I default return (-1) from Widget callback functions. **************************************************************************/ Uint16 widget_pressed_action(struct widget * pWidget) { Uint16 ID = 0; if (!pWidget) { return 0; } widget_info_counter = 0; if (pInfo_Area) { sdl_dirty_rect(*pInfo_Area); FC_FREE(pInfo_Area); FREESURFACE(pInfo_Label); } switch (get_wtype(pWidget)) { case WT_TI_BUTTON: case WT_I_BUTTON: case WT_ICON: case WT_ICON2: if (Main.event.button.button == SDL_BUTTON_LEFT) { set_wstate(pWidget, FC_WS_PRESSED); widget_redraw(pWidget); widget_mark_dirty(pWidget); flush_dirty(); set_wstate(pWidget, FC_WS_SELLECTED); SDL_Delay(300); } ID = pWidget->ID; if (pWidget->action) { if (pWidget->action(pWidget)) { ID = 0; } } break; case WT_EDIT: { if (Main.event.button.button == SDL_BUTTON_LEFT) { bool ret, loop = ((get_wflags(pWidget) & WF_EDIT_LOOP) == WF_EDIT_LOOP); enum Edit_Return_Codes change; do { ret = FALSE; change = edit_field(pWidget); if (change != ED_FORCE_EXIT && (!loop || change != ED_RETURN)) { widget_redraw(pWidget); widget_mark_dirty(pWidget); flush_dirty(); } if (change != ED_FORCE_EXIT && change != ED_ESC && pWidget->action) { if (pWidget->action(pWidget)) { ID = 0; } } if (loop && change == ED_RETURN) { ret = TRUE; } } while(ret); ID = 0; } break; } case WT_VSCROLLBAR: case WT_HSCROLLBAR: if (Main.event.button.button == SDL_BUTTON_LEFT) { set_wstate(pWidget, FC_WS_PRESSED); widget_redraw(pWidget); widget_mark_dirty(pWidget); flush_dirty(); } ID = pWidget->ID; if (pWidget->action) { if (pWidget->action(pWidget)) { ID = 0; } } break; case WT_CHECKBOX: case WT_TCHECKBOX: if (Main.event.button.button == SDL_BUTTON_LEFT) { set_wstate(pWidget, FC_WS_PRESSED); widget_redraw(pWidget); widget_mark_dirty(pWidget); flush_dirty(); set_wstate(pWidget, FC_WS_SELLECTED); togle_checkbox(pWidget); SDL_Delay(300); } ID = pWidget->ID; if (pWidget->action) { if (pWidget->action(pWidget)) { ID = 0; } } break; case WT_COMBO: if (Main.event.button.button == SDL_BUTTON_LEFT) { set_wstate(pWidget, FC_WS_PRESSED); combo_popup(pWidget); } else { combo_popdown(pWidget); } break; default: ID = pWidget->ID; if (pWidget->action) { if (pWidget->action(pWidget) != 0) { ID = 0; } } break; } return ID; }
/************************************************************************** Popup (or raise) the short player list dialog version. **************************************************************************/ void popup_players_nations_dialog(void) { struct widget *pWindow = NULL, *pBuf = NULL; SDL_Surface *pLogo = NULL; SDL_String16 *pStr; char cBuf[128], *state; int n = 0, w = 0, units_h = 0; const struct player_diplstate *pDS; SDL_Rect area; if (pShort_Players_Dlg) { return; } pShort_Players_Dlg = fc_calloc(1, sizeof(struct ADVANCED_DLG)); /* TRANS: Nations report title */ pStr = create_str16_from_char(_("Nations") , adj_font(12)); pStr->style |= TTF_STYLE_BOLD; pWindow = create_window_skeleton(NULL, pStr, 0); pWindow->action = players_nations_window_dlg_callback; set_wstate(pWindow, FC_WS_NORMAL); add_to_gui_list(ID_WINDOW, pWindow); pShort_Players_Dlg->pEndWidgetList = pWindow; area = pWindow->area; /* ---------- */ /* exit button */ pBuf = create_themeicon(pTheme->Small_CANCEL_Icon, pWindow->dst, WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND); pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"), adj_font(12)); area.w = MAX(area.w, pBuf->size.w + adj_size(10)); pBuf->action = exit_players_nations_dlg_callback; set_wstate(pBuf, FC_WS_NORMAL); pBuf->key = SDLK_ESCAPE; add_to_gui_list(ID_BUTTON, pBuf); /* ---------- */ players_iterate(pPlayer) { if (pPlayer != client.conn.playing) { if(!pPlayer->is_alive || is_barbarian(pPlayer)) { continue; } pDS = player_diplstate_get(client.conn.playing, pPlayer); if(pPlayer->ai_controlled) { state = _("AI"); } else { if (pPlayer->is_connected) { if (pPlayer->phase_done) { state = _("done"); } else { state = _("moving"); } } else { state = _("disconnected"); } } if(pDS->type == DS_CEASEFIRE) { fc_snprintf(cBuf, sizeof(cBuf), "%s(%s) - %d %s", nation_adjective_for_player(pPlayer), state, pDS->turns_left, PL_("turn", "turns", pDS->turns_left)); } else { fc_snprintf(cBuf, sizeof(cBuf), "%s(%s)", nation_adjective_for_player(pPlayer), state); } pStr = create_str16_from_char(cBuf, adj_font(10)); pStr->style |= TTF_STYLE_BOLD; pLogo = get_nation_flag_surface(nation_of_player(pPlayer)); pBuf = create_iconlabel(pLogo, pWindow->dst, pStr, (/*WF_FREE_THEME|*/WF_RESTORE_BACKGROUND|WF_DRAW_TEXT_LABEL_WITH_SPACE)); /* now add some eye candy ... */ switch (pDS->type) { case DS_ARMISTICE: pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_PLRDLG_ARMISTICE); set_wstate(pBuf, FC_WS_NORMAL); break; case DS_WAR: if(can_meet_with_player(pPlayer) || can_intel_with_player(pPlayer)) { set_wstate(pBuf, FC_WS_NORMAL); pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_PLRDLG_WAR); } else { pBuf->string16->fgcol = *(get_theme_color(COLOR_THEME_PLRDLG_WAR_RESTRICTED)); } break; case DS_CEASEFIRE: pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_PLRDLG_CEASEFIRE); set_wstate(pBuf, FC_WS_NORMAL); break; case DS_PEACE: pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_PLRDLG_PEACE); set_wstate(pBuf, FC_WS_NORMAL); break; case DS_ALLIANCE: pBuf->string16->fgcol = *get_theme_color(COLOR_THEME_PLRDLG_ALLIANCE); set_wstate(pBuf, FC_WS_NORMAL); break; case DS_NO_CONTACT: pBuf->string16->fgcol = *(get_theme_color(COLOR_THEME_WIDGET_DISABLED_TEXT)); break; default: set_wstate(pBuf, FC_WS_NORMAL); break; } pBuf->string16->bgcol = (SDL_Color) {0, 0, 0, 0}; pBuf->data.player = pPlayer; pBuf->action = player_nation_callback; add_to_gui_list(ID_LABEL, pBuf); area.w = MAX(w, pBuf->size.w); area.h += pBuf->size.h; if (n > 19) { set_wflag(pBuf, WF_HIDDEN); } n++; } } players_iterate_end; pShort_Players_Dlg->pBeginWidgetList = pBuf; pShort_Players_Dlg->pBeginActiveWidgetList = pShort_Players_Dlg->pBeginWidgetList; pShort_Players_Dlg->pEndActiveWidgetList = pWindow->prev->prev; pShort_Players_Dlg->pActiveWidgetList = pShort_Players_Dlg->pEndActiveWidgetList; /* ---------- */ if (n > 20) { units_h = create_vertical_scrollbar(pShort_Players_Dlg, 1, 20, TRUE, TRUE); pShort_Players_Dlg->pScroll->count = n; n = units_h; area.w += n; units_h = 20 * pBuf->size.h; } else { units_h = area.h; } /* ---------- */ area.h = units_h; resize_window(pWindow, NULL, NULL, (pWindow->size.w - pWindow->area.w) + area.w, (pWindow->size.h + pWindow->area.h) + area.h); area = pWindow->area; widget_set_position(pWindow, ((Main.event.motion.x + pWindow->size.w + adj_size(10) < Main.screen->w) ? (Main.event.motion.x + adj_size(10)) : (Main.screen->w - pWindow->size.w - adj_size(10))), ((Main.event.motion.y - adj_size(2) + pWindow->size.h < Main.screen->h) ? (Main.event.motion.y - adj_size(2)) : (Main.screen->h - pWindow->size.h - adj_size(10)))); w = area.w; if (pShort_Players_Dlg->pScroll) { w -= n; } /* exit button */ pBuf = pWindow->prev; pBuf->size.x = area.x + area.w - pBuf->size.w - 1; pBuf->size.y = pWindow->size.y + adj_size(2); /* cities */ pBuf = pBuf->prev; setup_vertical_widgets_position(1, area.x, area.y, w, 0, pShort_Players_Dlg->pBeginActiveWidgetList, pBuf); if (pShort_Players_Dlg->pScroll) { setup_vertical_scrollbar_area(pShort_Players_Dlg->pScroll, area.x + area.w, area.y, area.h, TRUE); } /* -------------------- */ /* redraw */ redraw_group(pShort_Players_Dlg->pBeginWidgetList, pWindow, 0); widget_mark_dirty(pWindow); flush_dirty(); }
/************************************************************************** Update all information in the player list dialog. **************************************************************************/ void real_players_dialog_update(void) { if(pPlayers_Dlg) { struct widget *pPlayer0, *pPlayer1; struct player *pPlayer; SDL_Rect dst0, dst1; int i; struct astring astr = ASTRING_INIT; /* redraw window */ widget_redraw(pPlayers_Dlg->pEndWidgetList); /* exit button -> neutral -> war -> casefire -> peace -> alliance */ pPlayer0 = pPlayers_Dlg->pEndWidgetList->prev->prev->prev->prev->prev->prev; do{ pPlayer0 = pPlayer0->prev; pPlayer1 = pPlayer0; pPlayer = pPlayer0->data.player; for (i = 0; i < num_player_dlg_columns; i++) { if (player_dlg_columns[i].show) { switch (player_dlg_columns[i].type) { case COL_TEXT: case COL_RIGHT_TEXT: astr_add_line(&astr, "%s: %s", player_dlg_columns[i].title, player_dlg_columns[i].func(pPlayer)); break; case COL_BOOLEAN: astr_add_line(&astr, "%s: %s", player_dlg_columns[i].title, player_dlg_columns[i].bool_func(pPlayer) ? _("Yes") : _("No")); break; default: break; } } } copy_chars_to_string16(pPlayer0->info_label, astr_str(&astr)); astr_free(&astr); /* now add some eye candy ... */ if(pPlayer1 != pPlayers_Dlg->pBeginWidgetList) { dst0.x = pPlayer0->size.x + pPlayer0->size.w / 2; dst0.y = pPlayer0->size.y + pPlayer0->size.h / 2; do{ pPlayer1 = pPlayer1->prev; if (have_diplomat_info_about(pPlayer) || have_diplomat_info_about(pPlayer1->data.player)) { dst1.x = pPlayer1->size.x + pPlayer1->size.w / 2; dst1.y = pPlayer1->size.y + pPlayer1->size.h / 2; switch (player_diplstate_get(pPlayer, pPlayer1->data.player)->type) { case DS_ARMISTICE: if(SDL_Client_Flags & CF_DRAW_PLAYERS_NEUTRAL_STATUS) { putline(pPlayer1->dst->surface, dst0.x, dst0.y, dst1.x, dst1.y, get_theme_color(COLOR_THEME_PLRDLG_ARMISTICE)); } break; case DS_WAR: if(SDL_Client_Flags & CF_DRAW_PLAYERS_WAR_STATUS) { putline(pPlayer1->dst->surface, dst0.x, dst0.y, dst1.x, dst1.y, get_theme_color(COLOR_THEME_PLRDLG_WAR)); } break; case DS_CEASEFIRE: if (SDL_Client_Flags & CF_DRAW_PLAYERS_CEASEFIRE_STATUS) { putline(pPlayer1->dst->surface, dst0.x, dst0.y, dst1.x, dst1.y, get_theme_color(COLOR_THEME_PLRDLG_CEASEFIRE)); } break; case DS_PEACE: if (SDL_Client_Flags & CF_DRAW_PLAYERS_PEACE_STATUS) { putline(pPlayer1->dst->surface, dst0.x, dst0.y, dst1.x, dst1.y, get_theme_color(COLOR_THEME_PLRDLG_PEACE)); } break; case DS_ALLIANCE: if (SDL_Client_Flags & CF_DRAW_PLAYERS_ALLIANCE_STATUS) { putline(pPlayer1->dst->surface, dst0.x, dst0.y, dst1.x, dst1.y, get_theme_color(COLOR_THEME_PLRDLG_ALLIANCE)); } break; default: /* no contact */ break; } } } while(pPlayer1 != pPlayers_Dlg->pBeginWidgetList); } } while(pPlayer0 != pPlayers_Dlg->pBeginWidgetList); /* -------------------- */ /* redraw */ redraw_group(pPlayers_Dlg->pBeginWidgetList, pPlayers_Dlg->pEndWidgetList->prev, 0); widget_mark_dirty(pPlayers_Dlg->pEndWidgetList); flush_dirty(); } }
/************************************************************************** ... **************************************************************************/ static int spy_steal_popup(struct widget *pWidget) { struct city *pVcity = pWidget->data.city; int id = MAX_ID - pWidget->ID; struct player *pVictim = NULL; struct CONTAINER *pCont; struct widget *pBuf = NULL; struct widget *pWindow; SDL_String16 *pStr; SDL_Surface *pSurf; int max_col, max_row, col, i, count = 0; SDL_Rect area; popdown_diplomat_dialog(); if(pVcity) { pVictim = city_owner(pVcity); } if (pDiplomat_Dlg || !pVictim) { return 1; } count = 0; advance_index_iterate(A_FIRST, i) { if (player_invention_reachable(client.conn.playing, i, FALSE) && TECH_KNOWN == player_invention_state(pVictim, i) && (TECH_UNKNOWN == player_invention_state(client.conn.playing, i) || TECH_PREREQS_KNOWN == player_invention_state(client.conn.playing, i))) { count++; } } advance_index_iterate_end; if(!count) { /* if there is no known tech to steal then send steal order at Spy's Discretion */ int target_id = pVcity->id; request_diplomat_action(DIPLOMAT_STEAL, id, target_id, advance_count()); return -1; } pCont = fc_calloc(1, sizeof(struct CONTAINER)); pCont->id0 = pVcity->id; pCont->id1 = id;/* spy id */ pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog)); pDiplomat_Dlg->diplomat_id = id; pDiplomat_Dlg->diplomat_target_id = pVcity->id; pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG)); pStr = create_str16_from_char(_("Select Advance to Steal"), adj_font(12)); pStr->style |= TTF_STYLE_BOLD; pWindow = create_window_skeleton(NULL, pStr, 0); pWindow->action = spy_steal_dlg_window_callback; set_wstate(pWindow , FC_WS_NORMAL); add_to_gui_list(ID_DIPLOMAT_DLG_WINDOW, pWindow); pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow; area = pWindow->area; area.w = MAX(area.w, adj_size(8)); /* ------------------ */ /* exit button */ pBuf = create_themeicon(pTheme->Small_CANCEL_Icon, pWindow->dst, WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND); pBuf->info_label = create_str16_from_char(_("Close Dialog (Esc)"), adj_font(12)); area.w += pBuf->size.w + adj_size(10); pBuf->action = exit_spy_steal_dlg_callback; set_wstate(pBuf, FC_WS_NORMAL); pBuf->key = SDLK_ESCAPE; add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf); /* ------------------------- */ count++; /* count + at Spy's Discretion */ /* max col - 104 is steal tech widget width */ max_col = (Main.screen->w - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104); /* max row - 204 is steal tech widget height */ max_row = (Main.screen->h - (pWindow->size.h - pWindow->area.h)) / adj_size(204); /* make space on screen for scrollbar */ if (max_col * max_row < count) { max_col--; } if (count < max_col + 1) { col = count; } else { if (count < max_col + adj_size(3)) { col = max_col - adj_size(2); } else { if (count < max_col + adj_size(5)) { col = max_col - 1; } else { col = max_col; } } } pStr = create_string16(NULL, 0, adj_font(10)); pStr->style |= (TTF_STYLE_BOLD | SF_CENTER); count = 0; advance_index_iterate(A_FIRST, i) { if (player_invention_reachable(client.conn.playing, i, FALSE) && TECH_KNOWN == player_invention_state(pVictim, i) && (TECH_UNKNOWN == player_invention_state(client.conn.playing, i) || TECH_PREREQS_KNOWN == player_invention_state(client.conn.playing, i))) { count++; copy_chars_to_string16(pStr, advance_name_translation(advance_by_number(i))); pSurf = create_sellect_tech_icon(pStr, i, FULL_MODE); pBuf = create_icon2(pSurf, pWindow->dst, WF_FREE_THEME | WF_RESTORE_BACKGROUND); set_wstate(pBuf, FC_WS_NORMAL); pBuf->action = spy_steal_callback; pBuf->data.cont = pCont; add_to_gui_list(MAX_ID - i, pBuf); if (count > (col * max_row)) { set_wflag(pBuf, WF_HIDDEN); } } } advance_index_iterate_end; /* get spy tech */ i = advance_number(unit_type(game_unit_by_number(id))->require_advance); copy_chars_to_string16(pStr, _("At Spy's Discretion")); pSurf = create_sellect_tech_icon(pStr, i, FULL_MODE); pBuf = create_icon2(pSurf, pWindow->dst, (WF_FREE_THEME | WF_RESTORE_BACKGROUND| WF_FREE_DATA)); set_wstate(pBuf, FC_WS_NORMAL); pBuf->action = spy_steal_callback; pBuf->data.cont = pCont; add_to_gui_list(MAX_ID - advance_count(), pBuf); count++; /* --------------------------------------------------------- */ FREESTRING16(pStr); pDiplomat_Dlg->pdialog->pBeginWidgetList = pBuf; pDiplomat_Dlg->pdialog->pBeginActiveWidgetList = pDiplomat_Dlg->pdialog->pBeginWidgetList; pDiplomat_Dlg->pdialog->pEndActiveWidgetList = pDiplomat_Dlg->pdialog->pEndWidgetList->prev->prev; /* -------------------------------------------------------------- */ i = 0; if (count > col) { count = (count + (col - 1)) / col; if (count > max_row) { pDiplomat_Dlg->pdialog->pActiveWidgetList = pDiplomat_Dlg->pdialog->pEndActiveWidgetList; count = max_row; i = create_vertical_scrollbar(pDiplomat_Dlg->pdialog, col, count, TRUE, TRUE); } } else { count = 1; } area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + i)); area.h = count * pBuf->size.h + adj_size(2); /* alloca window theme and win background buffer */ pSurf = theme_get_background(theme, BACKGROUND_SPYSTEALDLG); if (resize_window(pWindow, pSurf, NULL, (pWindow->size.w - pWindow->area.w) + area.w, (pWindow->size.h - pWindow->area.h) + area.h)) { FREESURFACE(pSurf); } area = pWindow->area; widget_set_position(pWindow, (Main.screen->w - pWindow->size.w) / 2, (Main.screen->h - pWindow->size.h) / 2); /* exit button */ pBuf = pWindow->prev; pBuf->size.x = area.x + area.w - pBuf->size.w - 1; pBuf->size.y = pWindow->size.y + adj_size(2); setup_vertical_widgets_position(col, area.x + 1, area.y, 0, 0, pDiplomat_Dlg->pdialog->pBeginActiveWidgetList, pDiplomat_Dlg->pdialog->pEndActiveWidgetList); if(pDiplomat_Dlg->pdialog->pScroll) { setup_vertical_scrollbar_area(pDiplomat_Dlg->pdialog->pScroll, area.x + area.w, area.y, area.h, TRUE); } redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, FALSE); widget_mark_dirty(pWindow); return -1; }