1 /* ShopPanel.h
2 Copyright (c) 2014 by Michael Zahniser
3 
4 Endless Sky is free software: you can redistribute it and/or modify it under the
5 terms of the GNU General Public License as published by the Free Software
6 Foundation, either version 3 of the License, or (at your option) any later version.
7 
8 Endless Sky is distributed in the hope that it will be useful, but WITHOUT ANY
9 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10 PARTICULAR PURPOSE.  See the GNU General Public License for more details.
11 */
12 
13 #ifndef SHOP_PANEL_H_
14 #define SHOP_PANEL_H_
15 
16 #include "Panel.h"
17 
18 #include "ClickZone.h"
19 #include "OutfitInfoDisplay.h"
20 #include "Point.h"
21 #include "ShipInfoDisplay.h"
22 
23 #include <map>
24 #include <set>
25 #include <string>
26 #include <vector>
27 
28 class Outfit;
29 class Planet;
30 class PlayerInfo;
31 class Ship;
32 
33 
34 
35 // Class representing the common elements of both the shipyard panel and the
36 // outfitter panel (e.g. the sidebar with the ships you own).
37 class ShopPanel : public Panel {
38 public:
39 	explicit ShopPanel(PlayerInfo &player, bool isOutfitter);
40 
41 	virtual void Step() override;
42 	virtual void Draw() override;
43 
44 protected:
45 	void DrawShipsSidebar();
46 	void DrawDetailsSidebar();
47 	void DrawButtons();
48 	void DrawMain();
49 
50 	void DrawShip(const Ship &ship, const Point &center, bool isSelected);
51 
52 	// These are for the individual shop panels to override.
53 	virtual int TileSize() const = 0;
54 	virtual int DrawPlayerShipInfo(const Point &point) = 0;
55 	virtual bool HasItem(const std::string &name) const = 0;
56 	virtual void DrawItem(const std::string &name, const Point &point, int scrollY) = 0;
57 	virtual int DividerOffset() const = 0;
58 	virtual int DetailWidth() const = 0;
59 	virtual int DrawDetails(const Point &center) = 0;
60 	virtual bool CanBuy(bool checkAlreadyOwned = true) const = 0;
61 	virtual void Buy(bool alreadyOwned = false) = 0;
62 	virtual void FailBuy() const = 0;
63 	virtual bool CanSell(bool toStorage = false) const = 0;
64 	virtual void Sell(bool toStorage = false) = 0;
65 	virtual void FailSell(bool toStorage = false) const;
66 	virtual bool CanSellMultiple() const;
67 	virtual bool IsAlreadyOwned() const;
68 	virtual bool ShouldHighlight(const Ship *ship);
69 	virtual void DrawKey();
70 	virtual void ToggleForSale();
71 	virtual void ToggleCargo();
72 
73 	// Only override the ones you need; the default action is to return false.
74 	virtual bool KeyDown(SDL_Keycode key, Uint16 mod, const Command &command, bool isNewPress) override;
75 	virtual bool Click(int x, int y, int clicks) override;
76 	virtual bool Hover(int x, int y) override;
77 	virtual bool Drag(double dx, double dy) override;
78 	virtual bool Release(int x, int y) override;
79 	virtual bool Scroll(double dx, double dy) override;
80 
81 	int64_t LicenseCost(const Outfit *outfit) const;
82 
83 
84 protected:
85 	class Zone : public ClickZone<const Ship *> {
86 	public:
87 		explicit Zone(Point center, Point size, const Ship *ship, double scrollY = 0.);
88 		explicit Zone(Point center, Point size, const Outfit *outfit, double scrollY = 0.);
89 
90 		const Ship *GetShip() const;
91 		const Outfit *GetOutfit() const;
92 
93 		double ScrollY() const;
94 
95 	private:
96 		double scrollY = 0.;
97 		const Outfit *outfit = nullptr;
98 	};
99 
100 	enum class ShopPane : int {
101 		Main,
102 		Sidebar,
103 		Info
104 	};
105 
106 
107 protected:
108 	static const int SIDEBAR_WIDTH = 250;
109 	static const int INFOBAR_WIDTH = 300;
110 	static const int SIDE_WIDTH = SIDEBAR_WIDTH + INFOBAR_WIDTH;
111 	static const int BUTTON_HEIGHT = 70;
112 	static const int SHIP_SIZE = 250;
113 	static const int OUTFIT_SIZE = 180;
114 
115 
116 protected:
117 	PlayerInfo &player;
118 	// Remember the current day, for calculating depreciation.
119 	int day;
120 	const Planet *planet = nullptr;
121 
122 	// The player-owned ship that was first selected in the sidebar (or most recently purchased).
123 	Ship *playerShip = nullptr;
124 	// The player-owned ship being reordered.
125 	Ship *dragShip = nullptr;
126 	bool isDraggingShip = false;
127 	Point dragPoint;
128 	// The group of all selected, player-owned ships.
129 	std::set<Ship *> playerShips;
130 
131 	// The currently selected Ship, for the ShipyardPanel.
132 	const Ship *selectedShip = nullptr;
133 	// The currently selected Outfit, for the OutfitterPanel.
134 	const Outfit *selectedOutfit = nullptr;
135 	// (It may be worth moving the above pointers into the derived classes in the future.)
136 
137 	double mainScroll = 0.;
138 	double sidebarScroll = 0.;
139 	double infobarScroll = 0.;
140 	double maxMainScroll = 0.;
141 	double maxSidebarScroll = 0.;
142 	double maxInfobarScroll = 0.;
143 	ShopPane activePane = ShopPane::Main;
144 	int mainDetailHeight = 0;
145 	int sideDetailHeight = 0;
146 	bool scrollDetailsIntoView = false;
147 	double selectedTopY = 0.;
148 	bool sameSelectedTopY = false;
149 	char hoverButton = '\0';
150 
151 	std::vector<Zone> zones;
152 	std::vector<ClickZone<std::string>> categoryZones;
153 
154 	std::map<std::string, std::set<std::string>> catalog;
155 	const std::vector<std::string> &categories;
156 	std::set<std::string> &collapsed;
157 
158 	ShipInfoDisplay shipInfo;
159 	OutfitInfoDisplay outfitInfo;
160 
161 	mutable Point warningPoint;
162 	mutable std::string warningType;
163 
164 
165 private:
166 	bool DoScroll(double dy);
167 	void SideSelect(int count);
168 	void SideSelect(Ship *ship);
169 	void MainLeft();
170 	void MainRight();
171 	void MainUp();
172 	void MainDown();
173 	std::vector<Zone>::const_iterator Selected() const;
174 	std::vector<Zone>::const_iterator MainStart() const;
175 	// Check if the given point is within the button zone, and if so return the
176 	// letter of the button (or ' ' if it's not on a button).
177 	char CheckButton(int x, int y);
178 };
179 
180 
181 
182 #endif
183