# copy_paste_gui.cpp

    00001 /* $Id: copy_paste_gui.cpp 4998 2006-05-28 07:45:14Z Frostregen $ */
    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 /* **** GUI Code for Copy&Paste **** */
    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     /* Set the button states according to variable content */
    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     /* Set image for tri-state button */
    00085     this->GetWidget<NWidgetCore>(CPW_TERRAIN)->widget_data = SPR_IMG_MINUS_TERRAIN + _copy_paste.m_paste_vacant_terrain;
    00086
    00087     this->DrawWidgets();
    00088
    00089     /* Draw CylinderGuy in CompanyColor, if unclicked */
    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           /* fallthrough */
    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           /* Toggle SignalDir */
    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       /* Set Selection size to Copy size */
    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           /* Reset SignalDir */
    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     /* UnclickWindowButtons "copy" and "paste" */
    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     /* If railtype has changed, we need to update our GUI */
    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() // When clicking the button in the terrain generation gui
    00301 {
    00302   AllocateWindowDescFront<CopyPasteWindow>(&_copy_paste_desc, 0);
    00303 }
    00304
    00305 void ShowCopyPasteToolbar(int button) // When using a shortcut
    00306 {
    00307   Window *w;
    00308   /* don't recreate the window if we're clicking on a button and the window exists. */
    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 }