00001
00002
00003 #include "stdafx.h"
00004 #include "openttd.h"
00005 #include "gui.h"
00006 #include "window_gui.h"
00007 #include "viewport_type.h"
00008 #include "viewport_func.h"
00009 #include "gfx_func.h"
00010 #include "strings_type.h"
00011 #include "clear_func.h"
00012 #include "window_type.h"
00013 #include "window_func.h"
00014 #include "sound_type.h"
00015 #include "sound_func.h"
00016 #include "tilehighlight_type.h"
00017 #include "tilehighlight_func.h"
00018 #include "company_func.h"
00019 #include "tile_type.h"
00020 #include "rail_type.h"
00021 #include "rail_gui.h"
00022 #include "sprite.h"
00023 #include "fios.h"
00024 #include "copy_paste.h"
00025 #include "table/sprites.h"
00026 #include "table/strings.h"
00027
00028
00030 static RailType _last_railtype = RAILTYPE_RAIL;
00031
00032
00033
00035 enum CopyPasteWidgets {
00036 CPW_CLOSEBOX = 0,
00037 CPW_CAPTION,
00038 CPW_STICKYBOX,
00039 CPW_SPACER_1,
00040 CPW_SPACER_2,
00041 CPW_SPACER_3,
00042 CPW_COPY,
00043 CPW_PASTE,
00044 CPW_LOAD,
00045 CPW_SAVE,
00046 CPW_ROTATE_LEFT,
00047 CPW_ROTATE_RIGHT,
00048 CPW_MIRROR_HORIZONTAL,
00049 CPW_MIRROR_VERTICAL,
00050 CPW_TERRAIN,
00051 CPW_DYNAMITE,
00052 CPW_RAIL,
00053 CPW_ROAD,
00054 CPW_REVERSE_SIGNALS,
00055 CPW_CONVERT_RAILTYPE,
00056 CPW_ONLY_OWN,
00057
00058 CPW_FIRST_CLICKABLE = CPW_COPY,
00059 CPW_LAST_CLICKABLE = CPW_ONLY_OWN,
00060 };
00061
00062 struct CopyPasteWindow : Window {
00063 int last_user_action;
00064 public:
00065 CopyPasteWindow(const WindowDesc *desc, WindowNumber window_number) : Window()
00066 {
00067 this->InitNested(desc, window_number);
00068 this->last_user_action = WIDGET_LIST_END;
00069
00070
00071 if (_copy_paste.m_clear_before_build) this->LowerWidget(CPW_DYNAMITE);
00072 if (_copy_paste.m_toggle_signal_direction) this->LowerWidget(CPW_REVERSE_SIGNALS);
00073 if (_copy_paste.m_convert_rail) this->LowerWidget(CPW_CONVERT_RAILTYPE);
00074 if (_copy_paste.m_copy_with_rail) this->LowerWidget(CPW_RAIL);
00075 if (_copy_paste.m_copy_with_road) this->LowerWidget(CPW_ROAD);
00076 if (_copy_paste.m_copy_with_other)this->LowerWidget(CPW_ONLY_OWN);
00077 }
00078
00079 virtual void OnPaint()
00080 {
00081 SetWidgetsDisabledState(!_copy_paste.IsSomethingCopied(), CPW_PASTE, CPW_SAVE,
00082 CPW_ROTATE_LEFT, CPW_ROTATE_RIGHT, CPW_MIRROR_HORIZONTAL, CPW_MIRROR_VERTICAL,
00083 WIDGET_LIST_END);
00084
00085 this->GetWidget<NWidgetCore>(CPW_TERRAIN)->widget_data = SPR_IMG_MINUS_TERRAIN + _copy_paste.m_paste_vacant_terrain;
00086
00087 this->DrawWidgets();
00088
00089
00090 if (!this->IsWidgetLowered(CPW_ONLY_OWN))
00091 DrawSprite(SPR_IMG_ONLY_OWN, COMPANY_SPRITE_COLOUR(_current_company), this->GetWidget<NWidgetCore>(CPW_ONLY_OWN)->pos_x + 1, this->GetWidget<NWidgetCore>(CPW_ONLY_OWN)->pos_y + 1);
00092 }
00093
00094 virtual void OnClick(Point pt, int widget, int click_count)
00095 {
00096 SetWidgetsDisabledState(!_copy_paste.IsSomethingCopied(), CPW_PASTE, CPW_SAVE,
00097 CPW_ROTATE_LEFT, CPW_ROTATE_RIGHT, CPW_MIRROR_HORIZONTAL, CPW_MIRROR_VERTICAL,
00098 WIDGET_LIST_END);
00099 if (this->IsWidgetDisabled(widget)) return;
00100 if ((widget >= CPW_FIRST_CLICKABLE) && (widget <= CPW_LAST_CLICKABLE)) {
00101 if (widget != CPW_COPY && widget != CPW_PASTE &&
00102 widget != CPW_DYNAMITE && widget != CPW_REVERSE_SIGNALS &&
00103 widget != CPW_RAIL && widget != CPW_CONVERT_RAILTYPE &&
00104 widget != CPW_ROAD && widget != CPW_ONLY_OWN) {
00105 this->HandleButtonClick(widget);
00106 }
00107 SndPlayFx(SND_15_BEEP);
00108 switch (widget) {
00109 case CPW_COPY:
00110 HandlePlacePushButton(this, CPW_COPY, SPR_CURSOR_COPY, HT_RECT);
00111 this->last_user_action = widget;
00112 break;
00113
00114 case CPW_PASTE:
00115 HandlePlacePushButton(this, CPW_PASTE, SPR_CURSOR_PASTE, HT_PREVIEW);
00116 this->last_user_action = widget;
00117 break;
00118
00119 case CPW_LOAD:
00120 _copy_paste.m_toggle_signal_direction = false;
00121
00122
00123 case CPW_SAVE:
00124 ShowSaveLoadDialog(widget == CPW_SAVE ? SLD_SAVE_TEMPLATE : SLD_LOAD_TEMPLATE);
00125 break;
00126
00127 case CPW_ROTATE_LEFT:
00128 case CPW_ROTATE_RIGHT:
00129 if (widget == CPW_ROTATE_LEFT) _copy_paste.RotateSelectionCCW();
00130 if (widget == CPW_ROTATE_RIGHT) _copy_paste.RotateSelectionCW();
00131 break;
00132
00133 case CPW_MIRROR_HORIZONTAL:
00134 case CPW_MIRROR_VERTICAL:
00135 if (widget == CPW_MIRROR_HORIZONTAL) _copy_paste.MirrorSelectionHorizontal();
00136 if (widget == CPW_MIRROR_VERTICAL) _copy_paste.MirrorSelectionVertical();
00137
00138
00139 this->OnClick(Point(), CPW_REVERSE_SIGNALS, 1);
00140 break;
00141
00142 case CPW_TERRAIN:
00143 _copy_paste.m_paste_vacant_terrain++;
00144 if (_copy_paste.m_paste_vacant_terrain > 2) _copy_paste.m_paste_vacant_terrain = 0;
00145 break;
00146
00147 case CPW_DYNAMITE: case CPW_REVERSE_SIGNALS:
00148 case CPW_RAIL: case CPW_CONVERT_RAILTYPE:
00149 case CPW_ROAD: case CPW_ONLY_OWN: {
00150 this->SetDirty();
00151 this->ToggleWidgetLoweredState(widget);
00152 bool state = IsWidgetLowered(widget);
00153 switch (widget) {
00154 case CPW_DYNAMITE: _copy_paste.m_clear_before_build = state; break;
00155 case CPW_RAIL: _copy_paste.m_copy_with_rail = state; break;
00156 case CPW_ROAD: _copy_paste.m_copy_with_road = state; break;
00157 case CPW_REVERSE_SIGNALS: _copy_paste.m_toggle_signal_direction = state; break;
00158 case CPW_CONVERT_RAILTYPE: _copy_paste.m_convert_rail = state; break;
00159 case CPW_ONLY_OWN: _copy_paste.m_copy_with_other = state; break;
00160 default: NOT_REACHED();
00161 }
00162 } break;
00163 default: break;
00164 }
00165
00166
00167 if (this->IsWidgetLowered(CPW_PASTE)) {
00168 if (_copy_paste.GetWidth() > 0)
00169 SetTileSelectSize(_copy_paste.GetWidth() - 1, _copy_paste.GetHeight() - 1);
00170 } else {
00171 SetTileSelectSize(1, 1);
00172 }
00173 }
00174 }
00175
00176 virtual void OnPlaceObject(Point pt, TileIndex tile)
00177 {
00178 switch (this->last_user_action) {
00179 case CPW_COPY:
00180 VpStartPlaceSizing(tile, VPM_X_AND_Y_LIMITED, DDSP_COPY_AREA);
00181 VpSetPlaceSizingLimit(255);
00182 break;
00183
00184 case CPW_PASTE:
00185 _copy_paste.PasteArea(tile);
00186 break;
00187 }
00188 }
00189
00190 virtual void OnPlaceDrag(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt)
00191 {
00192 VpSelectTilesWithMethod(pt.x, pt.y, select_method);
00193 }
00194
00195 virtual void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile)
00196 {
00197 if (pt.x != -1) {
00198 switch (select_proc) {
00199 case DDSP_COPY_AREA:
00200 _copy_paste.CopyArea(end_tile, start_tile);
00201
00202 if (_copy_paste.m_toggle_signal_direction) this->OnClick(Point(), CPW_REVERSE_SIGNALS, 1);
00203 this->SetDirty();
00204 break;
00205 default:
00206 break;
00207 }
00208 }
00209 }
00210
00211 virtual void OnPlaceObjectAbort()
00212 {
00213
00214 this->RaiseWidget(CPW_COPY);
00215 this->RaiseWidget(CPW_PASTE);
00216
00217 this->SetDirty();
00218 }
00219
00220 virtual void OnTimeout()
00221 {
00222 this->RaiseWidget(CPW_LOAD);
00223 this->RaiseWidget(CPW_SAVE);
00224 this->RaiseWidget(CPW_ROTATE_LEFT);
00225 this->RaiseWidget(CPW_ROTATE_RIGHT);
00226 this->RaiseWidget(CPW_MIRROR_HORIZONTAL);
00227 this->RaiseWidget(CPW_MIRROR_VERTICAL);
00228 this->RaiseWidget(CPW_TERRAIN);
00229 this->SetDirty();
00230 }
00231
00232 virtual void OnTick()
00233 {
00234
00235 if (_last_railtype != _cur_railtype) {
00236 const RailtypeInfo *rti = GetRailTypeInfo(_cur_railtype);
00237 _last_railtype = _cur_railtype;
00238 this->GetWidget<NWidgetCore>(CPW_CONVERT_RAILTYPE)->widget_data = rti->gui_sprites.convert_rail;
00239 this->SetDirty();
00240 }
00241 }
00242 };
00243
00244 static const NWidgetPart _nested_copy_paste_widgets[] = {
00245 NWidget(NWID_HORIZONTAL),
00246 NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN),
00247 NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetDataTip(STR_COPY_PASTE_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00248 NWidget(WWT_STICKYBOX, COLOUR_DARK_GREEN),
00249 EndContainer(),
00250 NWidget(NWID_HORIZONTAL),
00251 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_COPY), SetMinimalSize(22,22),
00252 SetFill(0, 1), SetDataTip(SPR_IMG_COPY, STR_COPY_PASTE_COPY_TOOLTIP),
00253 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_PASTE), SetMinimalSize(22,22),
00254 SetFill(0, 1), SetDataTip(SPR_IMG_PASTE, STR_COPY_PASTE_PASTE_TOOLTIP),
00255
00256 NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
00257
00258 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_LOAD), SetMinimalSize(22,22),
00259 SetFill(0, 1), SetDataTip(SPR_IMG_LOAD, STR_COPY_PASTE_LOAD_TOOLTIP),
00260 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_SAVE), SetMinimalSize(22,22),
00261 SetFill(0, 1), SetDataTip(SPR_IMG_SAVE, STR_COPY_PASTE_SAVE_TOOLTIP),
00262
00263 NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
00264
00265 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_ROTATE_LEFT), SetMinimalSize(22,22),
00266 SetFill(0, 1), SetDataTip(SPR_IMG_ROTATE_LEFT, STR_COPY_PASTE_ROTATE_LEFT_TOOLTIP),
00267 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_ROTATE_RIGHT), SetMinimalSize(22,22),
00268 SetFill(0, 1), SetDataTip(SPR_IMG_ROTATE_RIGHT, STR_COPY_PASTE_ROTATE_RIGHT_TOOLTIP),
00269 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_MIRROR_HORIZONTAL), SetMinimalSize(22,22),
00270 SetFill(0, 1), SetDataTip(SPR_IMG_MIRROR_HORIZONTAL, STR_COPY_PASTE_MIRROR_HORIZONTAL_TOOLTIP),
00271 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_MIRROR_VERTICAL), SetMinimalSize(22,22),
00272 SetFill(0, 1), SetDataTip(SPR_IMG_MIRROR_VERTICAL, STR_COPY_PASTE_MIRROR_VERTICAL_TOOLTIP),
00273
00274 NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetMinimalSize(4, 22), EndContainer(),
00275
00276 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_TERRAIN), SetMinimalSize(22,22),
00277 SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_TERRAIN, STR_COPY_PASTE_VACANT_TERRAIN_TOOLTIP),
00278 NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_DYNAMITE), SetMinimalSize(22,22),
00279 SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_DYNAMITE, STR_COPY_PASTE_BULLDOZE_BEFORE_BUILD_TOOLTIP),
00280 NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_RAIL), SetMinimalSize(22,22),
00281 SetFill(0, 1), SetDataTip(SPR_IMG_NO_RAIL, STR_COPY_PASTE_WITHOUT_RAIL_TOOLTIP),
00282 NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_ROAD), SetMinimalSize(22,22),
00283 SetFill(0, 1), SetDataTip(SPR_IMG_NO_ROAD, STR_COPY_PASTE_WITHOUT_ROAD_TOOLTIP),
00284 NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_REVERSE_SIGNALS), SetMinimalSize(22,22),
00285 SetFill(0, 1), SetDataTip(SPR_IMG_MINUS_SIGNAL, STR_COPY_PASTE_TOGGLE_SIGNAL_DIRECTION_TOOLTIP),
00286 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, CPW_CONVERT_RAILTYPE), SetMinimalSize(22,22),
00287 SetFill(0, 1), SetDataTip(SPR_IMG_CONVERT_RAIL, STR_COPY_PASTE_CONVERT_RAIL_TOOLTIP),
00288 NWidget(WWT_IMGBTN_2, COLOUR_DARK_GREEN, CPW_ONLY_OWN), SetMinimalSize(22,22),
00289 SetFill(0, 1), SetDataTip(SPR_IMG_ONLY_OWN, STR_COPY_PASTE_ONLY_OWN_TOOLTIP),
00290 EndContainer(),
00291 };
00292
00293 static const WindowDesc _copy_paste_desc(
00294 WDP_ALIGN_TOOLBAR, 0, 0,
00295 WC_COPY_PASTE, WC_SCEN_LAND_GEN,
00296 WDF_CONSTRUCTION,
00297 _nested_copy_paste_widgets, lengthof(_nested_copy_paste_widgets)
00298 );
00299
00300 void ShowCopyPasteToolbarGui()
00301 {
00302 AllocateWindowDescFront<CopyPasteWindow>(&_copy_paste_desc, 0);
00303 }
00304
00305 void ShowCopyPasteToolbar(int button)
00306 {
00307 Window *w;
00308
00309 if (button < CPW_FIRST_CLICKABLE || !(w = FindWindowById(WC_COPY_PASTE, 0))) {
00310 DeleteWindowByClass(WC_COPY_PASTE);
00311 w = new CopyPasteWindow(&_copy_paste_desc, 0);
00312 }
00313 if (w != NULL) w->OnClick(Point(), button, 1);
00314 }